使用構(gòu)造方法
var p1 = Point(2, 2);
var p2 = Point.fromJson({'x': 1, 'y': 2});
var p1 = new Point(2, 2);
var p2 = new Point.fromJson({'x': 1, 'y': 2});
上面這兩種寫法都是可以的慷嗜,Dart2中new關(guān)鍵字已經(jīng)成為一個(gè)可選項(xiàng)
常量構(gòu)造方法
有些類提供常量構(gòu)造函數(shù)卿捎。要使用常量構(gòu)造函數(shù)創(chuàng)建編譯時(shí)常量,請將const關(guān)鍵字放在構(gòu)造函數(shù)名稱之前
var p = const ImmutablePoint(2, 2);
構(gòu)造兩個(gè)相同的編譯時(shí)常量會產(chǎn)生一個(gè)規(guī)范的實(shí)例:
var a = const ImmutablePoint(1, 1);
var b = const ImmutablePoint(1, 1);
assert(identical(a, b)); // They are the same instance!
如果將const關(guān)鍵字前置的話,后面的const是可以省略的珍剑,比如
// Lots of const keywords here.
const pointAndLine = const {
'point': const [const ImmutablePoint(0, 0)],
'line': const [const ImmutablePoint(1, 10), const ImmutablePoint(-2, 11)],
};
上面的代碼可以寫成
// Only one const, which establishes the constant context.
const pointAndLine = {
'point': [ImmutablePoint(0, 0)],
'line': [ImmutablePoint(1, 10), ImmutablePoint(-2, 11)],
};
獲取運(yùn)行時(shí)類型
要在運(yùn)行時(shí)獲取對象的類型贫堰,可以使用Object的runtimeType屬性穆壕,該屬性返回Type對象。
print('The type of a is ${a.runtimeType}');
聲明構(gòu)造函數(shù)
class Point {
num x, y;
// Syntactic sugar for setting x and y
// before the constructor body runs.
Point(this.x, this.y);
}
上面是一種簡化版的構(gòu)造函數(shù)其屏,只是為了賦值喇勋,所以省略了方法體
如果您未聲明構(gòu)造函數(shù),則會為您提供默認(rèn)構(gòu)造函數(shù)偎行。
默認(rèn)構(gòu)造函數(shù)沒有參數(shù)川背,并在超類中調(diào)用無參數(shù)構(gòu)造函數(shù)。
命名構(gòu)造函數(shù)
使用命名構(gòu)造函數(shù)為類實(shí)現(xiàn)多個(gè)構(gòu)造函數(shù)或提供額外的清晰度:
class Point {
num x, y;
Point(this.x, this.y);
// Named constructor
Point.origin() {
x = 0;
y = 0;
}
}
跟Java等語言不同蛤袒,Dart的多重構(gòu)造方法是一種類名.自定義方法名來實(shí)現(xiàn)的熄云,如果你按照傳統(tǒng)的方法來寫的話,例如這樣:
class Grammar2 {
var x, y, z;
Grammar2(this.x,this.y); //錯(cuò)誤
Grammar2(this.x); //不能同時(shí)擁有兩個(gè)這樣的構(gòu)造函數(shù)
}
正確的寫法
class Grammar2 {
var x, y, z;
Grammar2.translate(this.x, this.y); //TODO 構(gòu)造方法的重載
Grammar2(this.x,this.y);
printRealVar() {
print('x=' + x.toString() + "y=" + y.toString());
return 2;
}
@override
String toString() {
// TODO: implement toString
return "this is Grammar2";
}
}
調(diào)用非默認(rèn)的超類構(gòu)造函數(shù)
默認(rèn)情況下妙真,子類中的構(gòu)造函數(shù)調(diào)用超類的未命名的無參數(shù)構(gòu)造函數(shù)缴允。
超類的構(gòu)造函數(shù)在構(gòu)造函數(shù)體的開頭被調(diào)用。
如果還使用初始化列表珍德,則在調(diào)用超類之前執(zhí)行练般。
總之,執(zhí)行順序如下:
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';
}
這段代碼的執(zhí)行結(jié)果就是:
in Person
in Employee
除了調(diào)用超類構(gòu)造函數(shù)之外锈候,還可以在構(gòu)造函數(shù)體運(yùn)行之前初始化實(shí)例變量薄料。
用冒號分隔初始化程序。
// 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)');
}
這個(gè)示例中泵琳,我們在調(diào)用fromjson這個(gè)構(gòu)造方法之前我們搶先初始化了x和y的值摄职,中間用冒號隔開
你也可以在調(diào)用初始化方法之前進(jìn)行一些參數(shù)的驗(yàn)證,比如:
Point.withAssert(this.x, this.y) : assert(x >= 0) {
print('In Point.withAssert(): ($x, $y)');
}
這個(gè)示例中获列,構(gòu)造方法調(diào)用之前琳钉,我們驗(yàn)證了x必須為正數(shù)
構(gòu)造函數(shù)的重定向
我們在開發(fā)中經(jīng)常會有這樣的情景,我們構(gòu)造了好幾個(gè)構(gòu)造方法蛛倦,但是這些構(gòu)造方法本身并不執(zhí)行任何操作歌懒,只是為了調(diào)用其他構(gòu)造 方法,在Dart中溯壶,我們稱之為構(gòu)造方法的重定向(這個(gè)語法在前面示例中出現(xiàn)過)
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);
}
常量構(gòu)造方法
假如你的示例在整個(gè)程序從始至終都不會變更實(shí)例及皂,這個(gè)時(shí)候你可以考慮一下使用常量構(gòu)造方法甫男,在構(gòu)造方法前面加上const關(guān)鍵字(是不是很像單例模式?)
class ImmutablePoint {
static final ImmutablePoint origin =
const ImmutablePoint(0, 0);
final num x, y;
const ImmutablePoint(this.x, this.y);
}
工廠構(gòu)造方法
跟工廠設(shè)計(jì)模式類似验烧,需要什么給你什么板驳,根據(jù)一個(gè)特定的標(biāo)識產(chǎn)生不同的實(shí)例,在Dart中碍拆,通過傳入一個(gè)特定的標(biāo)識符若治,來查看我的靜態(tài)緩存里面有沒有這個(gè)緩存,如果有感混,直接返回端幼,如果沒有,我便new 一個(gè)對象存入緩存再返回
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);
}
}
工廠構(gòu)造函數(shù)無權(quán)訪問 this
對象之間的操作符運(yùn)算
您可以覆蓋下表中顯示的運(yùn)算符弧满。
例如婆跑,如果定義Vector類,則可以定義一個(gè)+方法來添加兩個(gè)向量庭呜。(翻譯自官網(wǎng))
來個(gè)示例滑进,自己體會
class Vector {
final int x, y;
Vector(this.x, this.y);
Vector operator +(Vector v) => Vector(x + v.x, y + v.y);
Vector operator -(Vector v) => Vector(x - v.x, y - v.y);
// Operator == and hashCode not shown. For details, see note below.
// ···
}
void main() {
final v = Vector(2, 3);
final w = Vector(2, 2);
assert(v + w == Vector(4, 5));
assert(v - w == Vector(0, 1));
}
要在代碼嘗試使用不存在的方法或?qū)嵗兞繒r(shí)檢測或做出反應(yīng),您可以覆蓋noSuchMethod():
class A {
// Unless you override noSuchMethod, using a
// non-existent member results in a NoSuchMethodError.
@override
void noSuchMethod(Invocation invocation) {
print('You tried to use a non-existent member: ' +
'${invocation.memberName}');
}
}
枚舉類
enum Color { red, green, blue }
枚舉中的每個(gè)值都有一個(gè)索引getter募谎,它返回枚舉聲明中值的從零開始的位置扶关。
例如,第一個(gè)值具有索引0数冬,第二個(gè)值具有索引1节槐。
assert(Color.red.index == 0);
assert(Color.green.index == 1);
assert(Color.blue.index == 2);
要獲取枚舉中所有值的列表,請使用枚舉值常量吉执。
List<Color> colors = Color.values;
assert(colors[2] == Color.blue);
switch case中使用枚舉
var aColor = Color.blue;
switch (aColor) {
case Color.red:
print('Red as roses!');
break;
case Color.green:
print('Green as grass!');
break;
default: // Without this, you see a WARNING.
print(aColor); // 'Color.blue'
}
Mixin
Mixins是一種在多個(gè)類層次結(jié)構(gòu)中重用類代碼的方法,B繼承于A地来,但是B也要用到C的一些特性戳玫,多繼承在很多語言中是行不通的,Dart中的Mixin就是為了解決這種問題出現(xiàn)的
要使用mixin未斑,請使用with關(guān)鍵字咕宿,后跟一個(gè)或多個(gè)mixin名稱。
以下示例顯示了兩個(gè)使用mixins的類:
class Musician extends Performer with Musical {
// ···
}
class Maestro extends Person
with Musical, Aggressive, Demented {
Maestro(String maestroName) {
name = maestroName;
canConduct = true;
}
}
注意:要實(shí)現(xiàn)一個(gè)mixin蜡秽,創(chuàng)建一個(gè)擴(kuò)展Object的類府阀,聲明沒有構(gòu)造函數(shù),并且沒有調(diào)用super芽突。
例如:
abstract class Musical {
bool canPlayPiano = false;
bool canCompose = false;
bool canConduct = false;
void entertainMe() {
if (canPlayPiano) {
print('Playing piano');
} else if (canConduct) {
print('Waving hands');
} else {
print('Humming to self');
}
}
}
泛型方法(只看代碼不解釋试浙,跟java幾乎一樣)
T first<T>(List<T> ts) {
// Do some initial work or error checking, then...
T tmp = ts[0];
// Do some additional checking or processing...
return tmp;
}
導(dǎo)入
Dart目前都要手動(dòng)導(dǎo)入包,Dart內(nèi)置的library可以直接用import 'Interface.dart';方法導(dǎo)入寞蚌,自定義的包可以在前面加入一個(gè)package關(guān)鍵字導(dǎo)入
import 'package:flutter_app/Grammar2.dart';
import 'SuperGrammar.dart';
import 'Interface.dart';
import 'FactoryClass.dart';
import 'package:meta/meta.dart';
import 'ConstantClass.dart';
有一種情況例外田巴,加入導(dǎo)入的兩個(gè)包里面有同名的類钠糊,這個(gè)時(shí)候如何區(qū)分,java 是用全路徑來標(biāo)識壹哺,Dart里面可以給這個(gè)包里面所有的類設(shè)置一個(gè)別名
import 'package:lib1/lib1.dart';
import 'package:lib2/lib2.dart' as lib2; //這里利用as來設(shè)置 別名
// Uses Element from lib1.
Element element1 = Element();
// Uses Element from lib2.
lib2.Element element2 = lib2.Element();
如果你想導(dǎo)入的是一個(gè)包中的部分類
// Import only foo.
import 'package:lib1/lib1.dart' show foo;
// Import all names EXCEPT foo.
import 'package:lib2/lib2.dart' hide foo;
設(shè)置這個(gè)功能的出發(fā)點(diǎn)是可以降低包體積么抄伍??管宵? 不得而知
improt 懶加載
這個(gè)是為了在使用導(dǎo)入的類的時(shí)候才會去載入這個(gè)包截珍,主要是為了提升啟動(dòng)效率
如果需要使用懶加載的功能,請使用deferred as 關(guān)鍵字
import 'package:greetings/hello.dart' deferred as hello;
//需要的時(shí)候調(diào)用別名.loadLibiary方法
Future greet() async {
await hello.loadLibrary();
hello.printGreeting();
}
在前面的這段代碼中 await 關(guān)鍵字的作用是暫停程序的運(yùn)行直到包導(dǎo)入完成
延遲庫的常量不是導(dǎo)入文件中的常量箩朴。
請記住岗喉,在加載延遲庫之前,這些常量不存在隧饼。您不能在導(dǎo)入文件中使用延遲庫中的類型沈堡。
相反,請考慮將接口類型移動(dòng)到由延遲庫和導(dǎo)入文件導(dǎo)入的庫燕雁。Dart隱式地將loadLibrary()插入到使用deferred as namespace定義的命名空間中诞丽。loadLibrary()函數(shù)返回Future。