Dart的一些基础知识能够看Dart中文网,网上也有不少入门教程。这个系列只是我在学习过程颇有用,但一些基础教程中未说起的。json
Dart和Java在不少方面很类似,但也有不少不同的地方,好比:ide
可选命名参数函数
调用方法的时候,你可使用这种形式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}) { // ... }
可选命名参数经常使用于类的构造函数,看参看类-构造函数可选命名参数ui
可选位置参数this
把一些方法的参数放到[]
中就变成可选 位置参数了: String say(String from, String msg, [String device]) { var result = '$from says $msg'; if (device != null) { result = '$result with a $device'; } return result; }
下面是不使用可选参数调用上面方法 的示例:code
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'; }
下面是构造函数执行顺序: