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');
複製代碼