帶你Dart帶你Diao之類(一)
在前面的系列文章(文章末尾會有傳送門哦~~)都是些比較簡單的基礎概念,之後就要開始介紹一些注重理解和手動實踐的Dart知識了。這篇的內容主要是Dart中的類的構造方法。
Dart是一種面向物件的語言,具有類和基於mixin的繼承。每個物件都是一個類的例項,所有的類都是Object的子類。
核心內容如下
- 普通構造方法
- 常量構造方法
- 初始化列表
- 工廠構造方法
類的成員
和java語言類似,使用點號(.)引用例項變數或方法
var p = Point(2, 2); // Set the value of the instance variable y. p.y = 3;
但它還可以這麼寫
// If p is non-null, set its y value to 4.
p?.y = 4;
這是為避免最左運算元為空時出現異常,使用 ?.代替 .
構造方法
如果不宣告構造方法,則為您提供預設構造方法。預設構造方法沒有引數,並在超類中呼叫無引數建構函式。
如果有多個構造方法,構造方法的寫法和Java不太一樣。即使構造方法的引數不同,這些構造方法的命名也不能重複
那如果有多個構造方法,我們可以通過ClassName.identifier作為它的構造方法,比如下面的Point.fromJson
class Point{ var x; var y; Point(var x,var y){ this.x=x; this.y=y; } Point.fromJson(Map<String, int> map) { x=map['x']; y=map['y']; } }
呼叫構造方法
var p1 = new Point(2, 2);
var p2 = new Point.fromJson({'x': 1, 'y': 2});
當然我們這裡的new關鍵字是可以省略的
在Dart2中new關鍵字為可選關鍵字
class ImmutablePoint {
final num x, y;
const ImmutablePoint(this.x,this.y);//常量構造方法
}
常量構造方法需要新增關鍵字const,並且是沒有身體的,直接在末尾加;即可
var a = const ImmutablePoint(1, 1); var b = const ImmutablePoint(1, 1); assert(identical(a, b)); print(a==b); //true print(b); //Instance of 'ImmutablePoint'
構造兩個相同的編譯時常量會生成一個單一的、規範的例項
在常量上下文中,可以在建構函式或文字之前省略const。例如,它建立了一個const的 map集合
//這裡用來很多const
const pointAndLine = const {
'point': const [const ImmutablePoint(0, 0)],
'line': const [const ImmutablePoint(1, 10), const ImmutablePoint(-2, 11)],
};
//可以省略除第一個外的其他const
const pointAndLine = {
'point': [ImmutablePoint(0, 0)],
'line': [ImmutablePoint(1, 10), ImmutablePoint(-2, 11)],
};
上面的Point類我們可以這麼寫
Point.fromJson(Map<String, int> map):
x=map['x'],
y=map['y']{
print('In Point.fromJson(): ($x, $y)');
}
呼叫超類構造方法之外,還可以在建構函式主體執行之前初始化例項變數,初始值設定項用逗號分開。
可以通過在初始化列表中使用assert來驗證輸入
Point.withAssert(this.x, this.y) : assert(x >= 0) {
print('In Point.withAssert(): ($x, $y)');
}
這樣寫有什麼好處呢?
初始化列表在設定final欄位時很方便
我們在構造方法的body裡設定final變數是不能編譯通過,但通過這種方式就是ok的
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);
}
///執行結果
3.605551275463989
工廠構造方法可以從快取返回例項,也可以返回子型別的例項。
在實現構造方法時使用factory關鍵字,工廠構造方法並不總是建立類的新例項。
class Logger {
final String name;
bool mute = false;
//用於快取已經例項化的物件
static final Map<String, Logger> _cache =
<String, Logger>{};
factory Logger(String name) {
if (_cache.containsKey(name)) { //如果map快取裡存在直接返回例項
return _cache[name];
} else { //如果map快取裡不存在,則返回新的例項
final logger = Logger._test(String name):this.name=name;;
_cache[name] = logger;
return logger;
}
}
//???
Logger._internal(this.name);
void log(String msg) {
if (!mute) print(msg);
}
}
上面程式碼還是比較好理解的,不知道在我標記問號的那句程式碼你有沒有懵逼?反正我看的時候是感覺有點奇怪的。
其實仔細一研究,它其實等價於這樣的寫法
Logger._internal(String name):this.name=name;
Dart相關係列的傳送門