Dart4Flutter -01 – 变量, 类型和 函数json
Dart4Flutter -拾遗01 - flutter-dart环境搭建函数
flutter入门 - 状态管理post
经过建立一个和类名相同的函数声明一个构造函数(除此以外还有命名构造函数)。this
构造函数一般用来建立一个类的实例。spa
class Point {
num x, y;
Point(num x, num y) {
// There's a better way to do this, stay tuned.
this.x = x;
this.y = y;
}
}
复制代码
this
关键字指向当前实例3d
将构造函数的参数赋值给实例变量太常见了,dart有一个语法糖使这种状况更加便捷:
class Point {
num x, y;
// Syntactic sugar for setting x and y
// before the constructor body runs.
Point(this.x, this.y);
}
复制代码
若是你不声明构造函数,系统将提供一个默认的构造函数。默认的构造函数没有参数,并且将调用父类的无参数的构造函数。
子类不能从父类继承构造函数。声明无参数的构造函数的子类只有默认的构造函数,即没有参数、没有名字(相对于命名构造函数)。
经过命名构造函数实现一个类能够有多个构造函数,或者提供更有正对性的构造函数:
class Point {
num x, y;
Point(this.x, this.y);
// Named constructor
Point.origin() {
x = 0;
y = 0;
}
}
复制代码
注意:构造函数是不能继承的,因此子类是不能继承父类的命名构造函数的。若是你但愿使用父类中的构造函数建立子类的实例,你必须在子类中实现父类中的构造函数。
默认,子类的构造函数调用父类非命名、无参构造函数。父类的构造函数在构函数体以前调用。若是有初始化列表,初始化在父类构造函数以前执行。总之,执行顺序以下:
若是父类没有未命名、无参构造函数,那么你必须手动调用父类中的一个构造函数。注意:父类的构造函数调用在:
以后,构造函数体以前。
在以下的例子中,Employee类的构造函数调用他父类Person的命名构造函数。
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';
}
复制代码
由于父类构造函数的参数在调用以前会评估,因此参数能够是表达式,例如一个函数调用。
class Employee extends Person {
Employee() : super.fromJson(getDefaultData());
// ···
}
复制代码
注意:父类构造函数不能使用this
.例如,参数能够调用静态方法,可是不能调用实例方法。
除了调用父类的构造函数,你还能够在执行构造函数体以前初始化实例变量。用逗号分隔每一个初始化。
// Initializer list sets instance variables before
// the constructor body runs.
Point.fromJson(Map<String, num> json)
: x = json['x'],
y = json['y'] {
print('In Point.fromJson(): ($x, $y)');
}
复制代码
注意:初始化表达式的右边不能用this
.
在开发期间,你能够在出初始化列表中使用assert校验
输入:
Point.withAssert(this.x, this.y) : assert(x >= 0) {
print('In Point.withAssert(): ($x, $y)');
}
复制代码
设置final字段时,初始化列表仍是很方便的。下面你的例子中,在初始化裂变中初始化三个final变量
import 'dart:math';
class Point {
final num x;
final num y;
final num distanceFromOrigin;
Point(x, y)
: x = x,
y = y,
distanceFromOrigin = sqrt(x * x + y * y);
}
main() {
var p = new Point(2, 3);
print(p.distanceFromOrigin);
}
复制代码
有时一个构造函数的目的只是重定向到同类的另外一个构造函数。一个可重定向函数的函数体是空的,同时构造函数的调用是在冒号以后的。
class Point {
num x, y;
// The main constructor for this class.
Point(this.x, this.y);
// Delegates to the main constructor.
Point.alongXAxis(num x) : this(x, 0);
}
复制代码
若是一个对象是不会改变的,你能够讲这些对象建立为编译时常量。定义cost
构造函数,并且要确保全部的常量都是final的。
class ImmutablePoint {
static final ImmutablePoint origin =
const ImmutablePoint(0, 0);
final num x, y;
const ImmutablePoint(this.x, this.y);
}
复制代码
当你须要构造函数不是每次都建立一个新的对象时,使用factory
关键字。例如工程构造函数返回一个在缓存的中的实例或者返回一个子类的实例。
下面的例子说明,从缓存中返回实例:
class Logger {
final String name;
bool mute = false;
// _cache is library-private, thanks to
// the _ in front of its name.
static final Map<String, Logger> _cache =
<String, Logger>{};
factory Logger(String name) {
if (_cache.containsKey(name)) {
return _cache[name];
} else {
final logger = Logger._internal(name);
_cache[name] = logger;
return logger;
}
}
Logger._internal(this.name);
void log(String msg) {
if (!mute) print(msg);
}
}
复制代码
注意:工厂构造函数不能使用this
调用工厂构造函数,可使用new
关键字
var logger = Logger('UI');
logger.log('Button clicked');
复制代码