声明
本笔记是我自己在学习Dart语言基础的时候做的笔记。有些代码只是为了演示用法,不要纠结逻辑。
本笔记是站在一个Android开发者的角度上记录的,Dart中与Java相同的地方没有做记录,请谅解。阅读本笔记将默认你是一个Android或Java开发者。
一、声明变量与常量
Dart中声明变量有以下几种方式:
//第一种方式
var str = '这是字符串';
var str2 = "这是字符串2";
var str3 = '''
这是字符串3
这是字符串3的第二行
''';
var str4 = """
这是字符串4
这是字符串4的第二行
""";
var age = 24;
//第二种方式
String str = '这是字符串';
int age = 25;
Dart中的常量使用final
和const
关键字修饰,const
定义时就要赋值,final
可以使用时在赋值,final
也是运行时常量,在运行时也不能被修改。
//使用final定义。
final String name = '李四';
final int age = 24;
//使用const定义。
const String gender = '男';
const int height = 165;
二、自定义函数
1. 可选参数
可选参数的作用就类似Java语言中的方法重载。
/**
* 定义可选参数的自定义函数。
* @userName 为必传参数。
* @age 可选参数
*/
String printUserInfo(String userName, [int age]){
return "姓名:$userName-年龄:${age==null??"未知"}";
}
//调用演示
print(printUserInfo("张三"));
print(printUserInfo("李四", 24));
//输出结果
姓名:张三-年龄:未知
姓名:李四-年龄:24
2. 可选参数-带默认值
可选参数也支持赋值默认值,也就是说,如果调用方法的时候没有传该参数,那么就就会使用默认值赋值。
/**
* 定义可选参数的自定义函数。
* @userName 为必传参数。
* @gander 可选参数
* @age 可选参数
*/
String printUserInfo(String userName, [String gender='男', int age]){
return "姓名:$userName-性别:$gender-年龄:${age==null??"未知"}";
}
//调用演示
print(printUserInfo("张三"));
print(printUserInfo("小微", '女'));
//输出结果
姓名:张三-性别:男-年龄:未知
姓名:小微-性别:女-年龄:未知
3. 命名参数
命名参数几乎和可选参数一样,只是有以下两点不同:
1).写法不同,要将[]
中括号换成{}
花括号。
2).用法不同,可选参数在调用时必须按照方法中声明的顺序传参,而命名参数则不需要按照顺序。这是因为命名参数在传参时必须制定参数名。
/**
* 定义命名参数的自定义函数。
* @userName 为必传参数。
* @gander 可选参数
* @age 可选参数
*/
String printUserInfo(String userName, {String gender='男', int age=23}){
return "姓名:$userName-性别:$gender-年龄:$age";
}
//调用演示
print(printUserInfo("张三", age:20));
print(printUserInfo("小微", age:18, gender:'女'));
//输出结果
姓名:张三-性别:男-年龄:20
姓名:小微-性别:女-年龄:18
4. 把方法做为参数
其实就是参数类型为一个Function。
//第一种方式
void fn1(fn){
fn();
}
void fn2(){
print('这里是方法2');
}
//调用演示
fn1(fn2);
//第二种方式
var fn3 = (){
print('这里是方法3');
};
//调用演示
fn1(fn3);
//输出结果
这里是方法2
这里是方法3
5. 匿名函数
//无参匿名方法
var fun1 = (){
print('无参匿名方法');
};
//有参匿名方法
var fun2 = (String arg){
print(arg);
};
三、类
1. 权限修饰符
Dart语言中并没有像Java一样有public
、private
、protected
这些权限修饰符。Dart中只有一个权限修饰符_
(下划线)。下划线修饰符类似于Java中的默认修饰符,在同一个.dart文件中是公开的,不同的.dart文件中是私有的。
class Persion{
//私有成员变量姓名。
String _name;
//私有成员变量年龄
int _age;
//构造方法
Persion(String name, int age){
_init(name, age);
}
//私有init方法。
void _init(String name, int age){
this._name = name;
this._age = age;
}
//公共方法获取姓名。
String getName(){
return this._name;
}
//公共方法获取年龄。
int getAge(){
return this._age;
}
}
2. 构造方法
1). 默认的构造方法与Java一样,但Dart支持可选参数
2).命名构造
命名构造顾名思义就是给构造方法定义一个名字,在使用的时候直接使用这个名字即可,其实在使用时的代码看起来更像是Java中的静态方法,只是在静态方法中返回了这个对象而已。
class Persion{
String name;
int age;
/**
* 定义命名构造
*/
Persion.create(String name, int age){
this.name = name;
this.age = age;
}
}
//使用
var persion = Persion.create("张三", 23);
print("${persion.name}-${persion.age}")
//输出
张三-23
3. getter 和 setter 方法
Dart中的方法与Java中的方法一样,在调用时后面必须要跟上()
,比如persion.getName()
,但是使用get或set定义方法后就可以像成员变量一样使用。
class Persion{
String _name;
int _age;
/**
* 定义命名构造
*/
Persion(String name, int age){
this._name = name;
this._age = age;
}
get isBaby{
return this._age <= 2;
}
set age(int age){
this._age = age;
}
}
//使用
var persion = new Persion('张三', 23);
persion.age = 1;
print(persion.isBaby);
//输出
true
4. 初始化列表
在Dart中我们可以在构造方法执行之前初始化对象的变量。
class Persion{
String name;
int age;
/**
* 定义命名构造
*/
Persion(): this.name = '李四', this.age = 24{
}
}
//使用
var persion = new Persion();
print("${persion.name}-${persion.age}");
//输出
李四-24
5. 静态属性和静态方法
Dart中的静态属性和静态方法与Java中一致,静态方法中不能访问非静态成员,非静态方法中可以访问静态成员。
class Persion{
static String name = '王五';
static int age = 25;
static isBaby(){
return age <= 2;
}
}
//使用
print("${Persion.name}-${Persion.age}-${Persion.isBaby()}");
//输出
王五-25-false
6. 对象操作符
-
?
条件运算符var persion persion?.getName() //加上 ? 表示如果persion为null则不会getName方法,相当于非null判断。
as
类型转换符(强转)is
类型判断(相当于Java中的instanceOf)-
..
级联操作(连缀)class Persion{ String name; int age; void printInfo(){ print("$name-$age"); } } //使用 Persion persion = new Persion(); persion..name = '赵六' ..age = 36 ..printInfo(); //输出 赵六-26
7. 继承
Dart中关于继承的规则基本和Java一致。
class Persion{
String name;
int age;
Persion(String name, int age){
this.name = name;
this.age = age;
}
void printInfo(){
print("$name-$age");
}
}
class Man extends Persion{
Man(String name, int age) : super(name, age);//如果父类没有空参构造子类就必须要调用父类的构造。
}
//使用
var man = new Man('如花', 28)
man.printInfo()
//输出
如花-28
上面的代码是正常的继承关系,下面是被继承的类有命名构造。
class Persion{
String name;
int age;
Persion.create(String name, int age){
this.name = name;
this.age = age;
}
void printInfo(){
print("$name-$age");
}
}
class Man extends Persion{
Man(String name, int age) : super.create(name, age);//调用super的命名构造。
}
复写父类方法。
class Man extends Persion{
Man(String name, int age) : super.create(name, age);
//覆盖父类的方法
@override
void printInfo() {
print('我是一个男人');
}
}
其他的基本与Java一致,这里就不再详细记录了。
四、抽象类&接口
Dart中的抽象类充当了Java中的接口和抽象类,Dart中可以子类可以继承抽象类也可以实现抽象类接口。由于Dart中没有interface关键字所以定义接口时推荐使用抽象类,只是子类实现时不是使用extends
而是使用implements
。
1. 抽象类
abstract class Fruits{
String taste();
}
class Apple extends Fruits{
String name;
Apple(String this.name);
@override
String taste() {
return "${name}苹果又甜又脆";
}
}
//使用
Fruits fruits = new Apple("红富士");
print(fruits.taste());
//输出
红富士苹果又甜又脆
2. 接口
接口使用implements
关键字而不是extends
:
abstract class Fruits{
String taste();
}
class Apple implements Fruits{
String name;
Apple(String this.name);
@override
String taste() {
return "${name}苹果又甜又脆";
}
}
class Durian implements Fruits{
@override
String taste() {
return '榴莲味道臭臭的但吃起来香';
}
}
//使用
Fruits fruits = new Apple("烟台");
print(fruits.taste());
fruits = new Durian();
print(fruits.taste());
//输出
烟台苹果又甜又脆
榴莲味道臭臭的但吃起来香
使用implements
关键字实现和extends
继承,有什么区别?答案是,如果是用implements
的话,那么接口中的所有方法子类都必须要复写。如果使用extends
则只需要复写抽象方法即可。由此可以说明以下两点:
- 一个类到底是接口还是抽象类还是普通类,得看子类使用的是
extends
继承还是implements
实现。 - 抽象类中可以有抽象方法,也可以有非抽象方法,什么样的方法是抽象方法?没有方法体的方法就是抽象方法。
注意,Dart与Java一样,只可以多实现不可以多继承。
3. mixins混合类
混合类其实是一个类似多继承的这么一个功能。为什么说类似多继承?因为从代码上看,它确实很像多继承。但使用mixins还有以下几个条件:
- 做为mixins的类只能继承自Object,不能继承其他类。
- 做为mixins的类不能有构造函数。
- 一个类可以mixins多个mixins类。
- mixins绝不是继承,也不是接口,而是Dart语言的一种全新的特性。
class Persion{
void work(){
print('人类都需要工作');
}
}
class ET{
void address(){
print('外星人生活在其他星球');
}
}
//mixins混合类。
class A with Persion, ET {}
//使用
var a = new A();
//混合类a即有Persion的方法又有ET的方法。其实就是class A,把这两个类给混合在了一起。
a.work();
a.address();
//输出
人类都需要工作
外星人生活在其他星球
对混合类使用is
进行类型判断的时候,会满足它所混合的所有类。
var a = new A();
print(a is Persion);
print(a is ET);
//输出
true
true
五、泛型
Dart中的泛型与Java中的泛型在使用上基本没有什么区别。只是有一点暂时不是很清楚,那就是不知道Dart中有没有类型擦除的概念。写demo是发现使用泛型后传入不同类型的数据在运行时会报错,不知道这是不是意味着Dart语言没有类型擦除。关于类型擦除以后再来研究,以后再来补齐这里的资料。
六、库
每一个.dart文件就是一个库。
1. 系统库
import 'dart:convert';
import 'dart:io';
2. 自定义库
impot 'lib/Persion.dart';
3. 三方库
Pub包管理系统中的库。
三方库的使用方法有以下几步:
需要在自己的项目的根目录中创建一个pubspec.yaml文件。
在pubspec.yaml文件中配置三方库的名称、描述、依赖等信息。
运行 pub get 命令将三方库下载到本地。
-
在项目中要使用的.dart文件中引入三方库,例如:
import 'package:http/http.dart' as http;
4. 库的重命名
在导入的不同的库中存在相同名称的类时,直接使用类将会报错,因为编译器不知道你要使用的是哪个类,这时就需要用到库的重命名功能(导包时使用as
为库重命名)。
import 'persion1.dart';
import 'persion1.dart' as p2;
main(){
//构建persion1库中的Persion对象。
Persion persion = new Persion();
//构建persion2库中的Persion对象。
p2.Persion persion2 = p2.Persion();
}
七、同步异步
调用异步方法要使用await
关键字,而await
关键字必须在async
的方法中使用。async
就是把方法变成异步方法,await
就是等待异步方法执行完成。
main(List<String> args) async {
var reqServer = await HttpServer.bind('192.168.0.100', 8080);
print('服务已启动');
await for (HttpRequest req in reqServer) {
handleMessage(req);
}
}