Dart的一些基础知识可以看Dart中文网,网上也有很多入门教程。这个系列只是我在学习过程很有用,但一些基础教程中未提及的。
Dart和Java在很多方面很相似,但也有很多不一样的地方,比如:
- 在 Dart 中没有诸如 public、private、protected 这样的关键词。以 _ 开头,则该标识符 在库内是私有的
- Dart2中,可以不使用new关键字创建,也可以使用。
- Dart中一切都是对象,方法也是对象并且具有一种类型Function。
- Dart中变量初始值为null,即使是int类型也是null。
- ..........
函数
可选参数
-
可选命名参数
调用方法的时候,你可以使用这种形式paramName: value
来指定命名参数。例如:enableFlags(bold: true, hidden: false);
在定义方法的时候,使用
{param1, param2, …}
的形式来指定命名参数:/// Sets the [bold] and [hidden] flags to the values /// you specify. enableFlags({bool bold, bool hidden}) { // ... }
可选命名参数常用于类的构造函数,看参看类-构造函数可选命名参数
-
可选位置参数
把一些方法的参数放到[]
中就变成可选 位置参数了:String say(String from, String msg, [String device]) { var result = '$from says $msg'; if (device != null) { result = '$result with a $device'; } return result; }
下面是不使用可选参数调用上面方法 的示例:
assert(say('Bob', 'Howdy') == 'Bob says Howdy');
下面是使用可选参数调用上面方法的示例:
assert(say('Bob', 'Howdy', 'smoke signal') == 'Bob says Howdy with a smoke signal');
类
Dart中类的定义、继承、重载和Java差不多,如果你会Java那Dart的面向对象也就很简单。但还是存在一些差异性的地方
例如:实列化的时一般是new Point();,Dart中new是可选的,Java是必须的。
构造函数
常见的构造函数定义和Java一样,定义一个和类名字一样的方法就定义了一个构造函数,还可以带有其他可选的标识符:
class Point {
num x;
num y;
Point(num x, num y) {
// There's a better way to do this, stay tuned.
this.x = x;
this.y = y;
}
}
由于把构造函数参数赋值给实例变量的场景太常见了, Dart 提供了一个语法糖来简化这个操作:
class Point {
num x;
num y;
// Syntactic sugar for setting x and y
// before the constructor body runs.
Point(this.x, this.y);
}
构造函数可选命名参数
在看Flutter一些控件的源码时,经常能看到以下代码
const Text(this.data, {
Key key,
this.style,
this.strutStyle,
this.textAlign,
this.textDirection,
this.locale,
this.softWrap,
this.overflow,
this.textScaleFactor,
this.maxLines,
this.semanticsLabel,
}) : assert(data != null),
textSpan = null,
super(key: key);
构造函数也是函数,所以同样适用函数的可选命名参数,在加上Dart 提供了一个语法糖,所以可像以下代码调用
new Text('红色+黑色删除线+25号',
style: TextStyle(
color: const Color(0xffff0000),
),
)
初始化参数列表
在构造函数体执行可以初始化实例参数, 使用逗号分隔初始化表达式。
class Point {
num x;
num y;
Point(this.x, this.y);
// Initializer list sets instance variables before
// the constructor body runs.
Point.fromJson(Map jsonMap)
: x = jsonMap['x'],
y = jsonMap['y'] {
print('In Point.fromJson(): ($x, $y)');
}
}
警告: 初始化表达式等号右边的部分不能访问 this
。
初始化列表非常适合用来设置 final 变量的值。
重定向构造函数
有时候一个构造函数会调动类中的其他构造函数。 一个重定向构造函数是没有代码的,在构造函数声明后,使用 冒号调用其他构造函数。
class Point {
num x;
num y;
// The main constructor for this class.
Point(this.x, this.y);
// Delegates to the main constructor.
Point.alongXAxis(num x) : this(x, 0);
}
调用超类构造函数
默认情况下,子类的构造函数会自动调用超类的 无名无参数的默认构造函数。 超类的构造函数在子类构造函数体开始执行的位置调用。 如果提供了一个 initializer list(初始化参数列表) ,则初始化参数列表在超类构造函数执行之前执行。
如果超类没有无名无参数构造函数, 则你需要手工的调用超类的其他构造函数。 在构造函数参数后使用冒号 (:
) 可以调用 超类构造函数。
class Person {
String firstName;
Person.fromJson(Map data) {
print('in Person');
}
}
class Employee extends Person {
// Person does not have a default constructor;
// you must call super.fromJson(data).
Employee.fromJson(Map data) : super.fromJson(data) {
print('in Employee');
}
}
main() {
var emp = new Employee.fromJson({});
// Prints:
// in Person
// in Employee
if (emp is Person) {
// Type check
emp.firstName = 'Bob';
}
(emp as Person).firstName = 'Bob';
}
下面是构造函数执行顺序:
- initializer list(初始化参数列表)
- superclass’s no-arg constructor(超类的无名构造函数)
- main class’s no-arg constructor(主类的无名构造函数)