dart是一種面向?qū)ο蟮恼Z(yǔ)言,具有類(lèi)和基于mixin的繼承脸爱。每個(gè)對(duì)象都是一個(gè)類(lèi)的實(shí)例,所有的類(lèi)都是
Object
的子類(lèi)毡代≡母基于mixin的繼承意味著,盡管每個(gè)類(lèi)(Object除外)只有一個(gè)超類(lèi)教寂,但一個(gè)類(lèi)主體可以在多個(gè)類(lèi)層次中重用捏鱼。
使用類(lèi)成員
對(duì)象的成員包括函數(shù)和數(shù)據(jù)(分別是方法和實(shí)例變量)。當(dāng)你調(diào)用一個(gè)方法時(shí)酪耕,你在一個(gè)對(duì)象上調(diào)用它:這個(gè)方法可以訪問(wèn)那個(gè)對(duì)象的函數(shù)和數(shù)據(jù)导梆。
使用點(diǎn)(.
)引用實(shí)例變量或方法:
var p = Point(2, 2);
// 設(shè)置實(shí)例變量要的值
p.y = 3;
// 獲取y的值
assert(p.y == 3);
// 在p上調(diào)用 distanceTo()
num distance = p.distanceTo(Point(4, 4));
使用?.
而不是.
為了避免最左邊的操作對(duì)象為空時(shí)出現(xiàn)異常:
// 如果p不為空,設(shè)置它的變量y的值為4
p?.y = 4;
使用構(gòu)造函數(shù)
你可以使用一個(gè)創(chuàng)建函數(shù)來(lái)創(chuàng)建對(duì)象迂烁。構(gòu)造函數(shù)的名字可以是ClassName
或者ClassName.indentifier
看尼。例如:以下的代碼創(chuàng)建Point
對(duì)象使用Point()
和Point.formJson()
構(gòu)造函數(shù):
var p1 = Point(2, 2);
var p2 = Point.fromJson({'x': 1, 'y': 2});
以下代碼實(shí)現(xiàn)同樣的效果,但是在構(gòu)造函數(shù)名稱(chēng)前使用了可選的new
關(guān)鍵字:
var p1 = new Point(2, 2);
var p2 = new Point.fromJson({'x': 1, 'y': 2});
版本說(shuō)明:
key
關(guān)鍵詞在版本2中為可選使用
一些類(lèi)提供常量構(gòu)造函數(shù)constant constructors
盟步。使用一個(gè)常量構(gòu)造函數(shù)去創(chuàng)建一個(gè)編譯時(shí)常量藏斩,將 const
關(guān)鍵詞放在構(gòu)造函數(shù)名稱(chēng)之前:
var p = const ImmutablePoint(2, 2);
構(gòu)造兩個(gè)相同的編譯時(shí)常量會(huì)產(chǎn)生一個(gè)規(guī)范的實(shí)例:
var a = const ImmutablePoint(1, 1);
var b = const ImmutablePoint(1, 1);
assert(identical(a, b)); //他們是同一個(gè)對(duì)象
在常量上下文中,可以省略構(gòu)造函數(shù)或常量前面的const
却盘。例如狰域,看看這個(gè)代碼媳拴,它創(chuàng)建了一個(gè)const map
:
//一大堆const關(guān)鍵詞
const pointAndLine = const {
'point': const [const ImmutablePoint(0, 0)],
'line': const [const ImmutablePoint(1, 10), const ImmutablePoint(-2, 11)],
};
除了第一次使用const
關(guān)鍵字以外,您可以省略所有的:
// 只有一個(gè)const兆览,它建立了恒定的上下文屈溉。
const pointAndLine = {
'point': [ImmutablePoint(0, 0)],
'line': [ImmutablePoint(1, 10), ImmutablePoint(-2, 11)],
};
如果常量構(gòu)造函數(shù)在常量上下文之外,并且在沒(méi)有const
的情況下被調(diào)用抬探,那么它會(huì)創(chuàng)建一個(gè)非常量對(duì)象:
var a = const ImmutablePoint(1, 1); // 創(chuàng)建一個(gè)常量
var b = ImmutablePoint(1, 1); //沒(méi)有常見(jiàn)一個(gè)常量
assert(!identical(a, b)); //兩者不是相同對(duì)象子巾!
版本說(shuō)明:
const
關(guān)鍵字在Dart 2中的恒定上下文中變得可選。
獲取對(duì)象的類(lèi)型
在運(yùn)行時(shí)獲取對(duì)象的類(lèi)型小压,你可以使用對(duì)象的runtimeType
屬性线梗,該屬性返回一個(gè)Type
對(duì)象
print('The type of a is ${a.runtimeType}');
到目前為止,你已經(jīng)知道如何使用類(lèi)场航。接下去剩余的章節(jié)展示如何去實(shí)現(xiàn)類(lèi)缠导。
對(duì)象變量
這里展示你如何聲明對(duì)象的變量:
class Point {
num x; // 聲明變量x,初始化為null
num y; // 聲明變量y溉痢,初始化為null
num z = 0; // 聲明變量z僻造,初始化為0
}
所有未初始化的對(duì)象變量擁有值null
所有實(shí)例變量都生成隱式getter
方法。Non-final實(shí)例變量也生成隱式setter
方法孩饼。
class Point {
num x;
num y;
}
void main() {
var point = Point();
point.x = 4; // 對(duì)x使用setter方法
assert(point.x == 4); // 對(duì)x使用getter法
assert(point.y == null); // 值默認(rèn)為空髓削。
}
如果初始化聲明實(shí)例變量量(該變量不是在構(gòu)造函數(shù)或方法中),則在創(chuàng)建實(shí)例時(shí)設(shè)置該值镀娶,該值在構(gòu)造函數(shù)及其初始值列表之前執(zhí)行立膛。
構(gòu)造函數(shù)
通過(guò)創(chuàng)建一個(gè)與其類(lèi)同名的函數(shù)來(lái)聲明一個(gè)構(gòu)造函數(shù)(另外,還可以添加一個(gè)附加標(biāo)識(shí)符梯码,如命名構(gòu)造函數(shù)中所述)宝泵。最常見(jiàn)的構(gòu)造函數(shù)形式——生成構(gòu)造函數(shù)——?jiǎng)?chuàng)建了一個(gè)類(lèi)的新實(shí)例:
class Point {
num x, y;
Point(num x, num y) {
//有更好的方法來(lái)做到這一點(diǎn),請(qǐng)繼續(xù)往下看
this.x = x;
this.y = y;
}
}
this
關(guān)鍵詞引用到當(dāng)前的對(duì)象
注:只有在名稱(chēng)沖突時(shí)才使用此選項(xiàng)。否則轩娶,Dart樣式會(huì)忽略這個(gè)儿奶。
將構(gòu)造函數(shù)參數(shù)分配給實(shí)例變量的模式非常常見(jiàn),Dart有語(yǔ)法糖以方便創(chuàng)建對(duì)象構(gòu)造器:
class Point {
num x, y;
// 在構(gòu)造函數(shù)運(yùn)行前鳄抒,語(yǔ)法糖會(huì)幫助設(shè)置x和y
Point(this.x, this.y);
}
默認(rèn)的構(gòu)造函數(shù)
如果不聲明構(gòu)造函數(shù)闯捎,則會(huì)為你提供默認(rèn)構(gòu)造函數(shù)。默認(rèn)構(gòu)造函數(shù)沒(méi)有參數(shù)许溅,并調(diào)用超類(lèi)中的無(wú)參數(shù)構(gòu)造函數(shù)瓤鼻。
構(gòu)造函不能被繼承
子類(lèi)不從它們的超類(lèi)繼承構(gòu)造函數(shù)。聲明沒(méi)有構(gòu)造函數(shù)的子類(lèi)只有默認(rèn)(沒(méi)有參數(shù)贤重,沒(méi)有名稱(chēng))構(gòu)造函數(shù)茬祷。
命名構(gòu)造函數(shù)
使用命名構(gòu)造函數(shù)為一個(gè)類(lèi)實(shí)現(xiàn)多個(gè)構(gòu)造函數(shù),或者提供額外的聲明:
class Point {
num x, y;
Point(this.x, this.y);
//命名構(gòu)造函數(shù)
Point.origin() {
x = 0;
y = 0;
}
}
請(qǐng)記住并蝗,構(gòu)造函數(shù)不是繼承的牲迫,這意味著超類(lèi)的命名構(gòu)造函數(shù)不是由子類(lèi)繼承的耐朴。如果你希望使用超類(lèi)中定義的命名構(gòu)造函數(shù)創(chuàng)建子類(lèi),則必須在子類(lèi)中實(shí)現(xiàn)該構(gòu)造函數(shù)盹憎。
調(diào)用 非默認(rèn)超類(lèi) 構(gòu)造函數(shù)
默認(rèn)情況下,子類(lèi)中的構(gòu)造函數(shù)調(diào)用超類(lèi)的未命名無(wú)參數(shù)構(gòu)造函數(shù)铐刘。超類(lèi)的構(gòu)造函數(shù)在構(gòu)造函數(shù)主體的開(kāi)頭被調(diào)用陪每。如果初始值列表也被使用,它會(huì)在調(diào)用超類(lèi)之前執(zhí)行镰吵¢莺蹋總之,執(zhí)行順序如下:
- 初始值列表
- 超類(lèi)的無(wú)參構(gòu)造器
- 主類(lèi)的無(wú)參構(gòu)造器
如果超類(lèi)沒(méi)有未命名的無(wú)參數(shù)構(gòu)造函數(shù)疤祭,則必須手動(dòng)調(diào)用超類(lèi)中的一個(gè)構(gòu)造函數(shù)盼产。在冒號(hào)(:
)后面指定超類(lèi)構(gòu)造函數(shù),就在構(gòu)造函數(shù)主體(如果有的話)前面勺馆。
在以下示例中戏售,Employee類(lèi)的構(gòu)造函數(shù)調(diào)用其超類(lèi)Person的命名構(gòu)造函數(shù)。
class Person {
String firstName;
Person.fromJson(Map data) {
print('in Person');
}
}
class Employee extends Person {
Employee.fromJson(Map data) : super.fromJson(data) {
print('in Employee');
}
}
main() {
var emp = new Employee.fromJson({});
if (emp is Person) {
// 類(lèi)型檢查
emp.firstName = '永動(dòng)機(jī)';
}
(emp as Person).firstName = '永動(dòng)機(jī)';
}
-------------------------------------------------------------------
in Person
in Employee
因?yàn)槌?lèi)構(gòu)造函數(shù)的參數(shù)是在調(diào)用構(gòu)造函數(shù)之前評(píng)估的草穆,所以參數(shù)可以是表達(dá)式灌灾,如函數(shù)調(diào)用:
class Employee extends Person {
Employee() : super.fromJson(getDefaultData());
// ···
}
警告:超類(lèi)構(gòu)造函數(shù)的參數(shù)沒(méi)有訪問(wèn)
this
的權(quán)限。例如悲柱,參數(shù)可以調(diào)用靜態(tài)方法锋喜,但不能調(diào)用實(shí)例方法。
初始值列表
除了調(diào)用超類(lèi)構(gòu)造函數(shù)豌鸡,還可以在構(gòu)造函數(shù)主體運(yùn)行之前初始化實(shí)例變量嘿般。用逗號(hào)分隔初始值設(shè)定項(xiàng)。
// 初始值列表在構(gòu)造函數(shù)運(yùn)行前初始化對(duì)象變量
Point.fromJson(Map<String, num> json)
: x = json['x'],
y = json['y'] {
print('In Point.fromJson(): ($x, $y)');
}
警告:初始值設(shè)定項(xiàng)的右側(cè)沒(méi)有訪問(wèn)
this
的權(quán)限涯冠。
在開(kāi)發(fā)過(guò)程中炉奴,你可以使用初始值列表中的assert來(lái)驗(yàn)證輸入。
Point.withAssert(this.x, this.y) : assert(x >= 0) {
print('In Point.withAssert(): ($x, $y)');
}
初始值列表在設(shè)置final字段時(shí)非常方便功偿。下面的示例初始化初始值列表中的三個(gè)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);
}
----------------------------------------------------------------------
3.605551275463989
重定向構(gòu)造函數(shù)
有時(shí)構(gòu)造函數(shù)的唯一目的是重定向到同一類(lèi)中的另一個(gè)構(gòu)造函數(shù)。重定向構(gòu)造函數(shù)的主體為空械荷,構(gòu)造函數(shù)調(diào)用出現(xiàn)在冒號(hào)( :
)之后共耍。
class Point {
num x, y;
// 這個(gè)類(lèi)的主構(gòu)造函式。
Point(this.x, this.y);
// 委托給主構(gòu)造函數(shù)吨瞎。
Point.alongXAxis(num x) : this(x, 0);
}
常量構(gòu)造函數(shù)
如果你的類(lèi)創(chuàng)建的對(duì)象從不改變痹兜,你可以創(chuàng)建一些編譯時(shí)的常量對(duì)象。因此颤诀,定義一個(gè)const
構(gòu)造函數(shù)字旭,且保證所有的對(duì)象變量都是final对湃。
class ImmutablePoint {
static final ImmutablePoint origin =
const ImmutablePoint(0, 0);
final num x, y;
const ImmutablePoint(this.x, this.y);
}
工廠構(gòu)造函數(shù)
在實(shí)現(xiàn)一個(gè)構(gòu)造函數(shù)時(shí)使用factory
關(guān)鍵字,該構(gòu)造函數(shù)并不總是創(chuàng)建其類(lèi)的新實(shí)例遗淳。例如拍柒,工廠構(gòu)造函數(shù)可能會(huì)從緩存中返回實(shí)例,也可能會(huì)返回子類(lèi)型的實(shí)例屈暗。
下面的示例演示從緩存返回對(duì)象的工廠構(gòu)造函數(shù):
class Logger {
final String name;
bool mute = false;
// _cache是私有變量
//_在名稱(chēng)前拆讯,表示該變量為私有
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)造者對(duì)
this
沒(méi)有訪問(wèn)權(quán)限。
像調(diào)用任何其他構(gòu)造函數(shù)一樣調(diào)用工廠構(gòu)造函數(shù):
var logger = Logger('UI');
logger.log('Button clicked');
方法
方法是為對(duì)象提供行為的函數(shù)养叛。
實(shí)例方法
在對(duì)象的實(shí)例方法有權(quán)限獲取對(duì)象變量和this
种呐,在接下來(lái)的例子里distanceTo
就是一個(gè)對(duì)象方法:
import 'dart:math';
class Point {
num x, y;
Point(this.x, this.y);
num distanceTo(Point other) {
var dx = x - other.x;
var dy = y - other.y;
return sqrt(dx * dx + dy * dy);
}
}
Getters 和 setters
getters 和 setters 是提供對(duì)對(duì)象屬性的讀寫(xiě)訪問(wèn)的特殊方法∑回想一下爽室,每個(gè)實(shí)例變量都有一個(gè)隱式getter,如果合適的話淆攻,還有一個(gè)setter阔墩。你可以通過(guò)使用get
和set
關(guān)鍵字實(shí)現(xiàn)getters和setters來(lái)創(chuàng)建其他屬性:
class Rectangle {
num left, top, width, height;
Rectangle(this.left, this.top, this.width, this.height);
// 定義兩個(gè)計(jì)算屬性:右側(cè)和底部。
num get right => left + width;
set right(num value) => left = value - width;
num get bottom => top + height;
set bottom(num value) => top = value - height;
}
void main() {
var rect = Rectangle(3, 4, 20, 15);
assert(rect.left == 3);
rect.right = 12;
assert(rect.left == -8);
}
使用getters和setters卜录,您可以從實(shí)例變量開(kāi)始戈擒,然后用方法包裝它們,所有這些都不需要更改客戶(hù)端代碼艰毒。
注意:無(wú)論是否明確定義了getter筐高,increment ( ++ )等運(yùn)算符都以預(yù)期的方式工作。為了避免任何意外的副作用丑瞧,操作只調(diào)用getter一次柑土,將其值保存在一個(gè)臨時(shí)變量中。
抽象方法
對(duì)象绊汹、getter和setter方法可以是抽象的稽屏,定義一個(gè)接口,但將其實(shí)現(xiàn)留給其他類(lèi)西乖。抽象方法只存在于抽象類(lèi)中狐榔。
要使方法抽象,請(qǐng)使用分號(hào)(;
)而不是方法體:
abstract class Doer {
//定義對(duì)象變量和方法...
void doSomething(); //定義抽象方法
}
class EffectiveDoer extends Doer {
void doSomething() {
// 提供一個(gè)實(shí)現(xiàn)获雕,因此該方法在這里不是抽象的...
}
}
抽象的類(lèi)
使用abstract
修飾符來(lái)定義一個(gè)抽象類(lèi)(一個(gè)類(lèi)不能被實(shí)例化)抽象類(lèi)對(duì)于定義接口是非常有用的薄腻,經(jīng)常有一些實(shí)現(xiàn)。如果你的抽象類(lèi)想要能被實(shí)例化届案,請(qǐng)定義工廠構(gòu)造函數(shù)
抽象類(lèi)里的抽象方法
// 此對(duì)象愛(ài)你過(guò)是抽象類(lèi)庵楷,因此不能被實(shí)例化
abstract class AbstractContainer {
// 定義構(gòu)造函數(shù)、字段、方法...
void updateChildren(); // 抽象方法
}
隱式接口
每個(gè)類(lèi)隱式定義一個(gè)接口尽纽,該接口包含該類(lèi)及其實(shí)現(xiàn)的任何接口的所有實(shí)例成員咐蚯。如果你想創(chuàng)建一個(gè)不繼承B實(shí)現(xiàn)而支持B類(lèi)API的A類(lèi),A類(lèi)應(yīng)該實(shí)現(xiàn)B接口弄贿。
一個(gè)類(lèi)通過(guò)在implements
子句中聲明一個(gè)或多個(gè)接口春锋,然后提供接口所需的API來(lái)實(shí)現(xiàn)這些接口。例如:
// 隱式接口包含 greet()
class Person {
// 在接口中挎春,但僅在此類(lèi)中可見(jiàn)看疙。
final _name;
//不在接口中,因?yàn)檫@是構(gòu)造函數(shù)直奋。
Person(this._name);
// 在接口中
String greet(String who) => 'Hello, $who. I am $_name.';
}
// 實(shí)現(xiàn)了Person接口
class Impostor implements Person {
get _name => '';
String greet(String who) => 'Hi $who. Do you know who I am?';
}
String greetBob(Person person) => person.greet('Bob');
void main() {
print(greetBob(Person('Kathy')));
print(greetBob(Impostor()));
}
下面是一個(gè)指定一個(gè)類(lèi)實(shí)現(xiàn)多個(gè)接口的示例:
class Point implements Comparable, Location {...}
擴(kuò)展類(lèi)
使用extends
去創(chuàng)建子類(lèi),super
去引用超類(lèi):
class Television {
void turnOn() {
_illuminateDisplay();
_activateIrSensor();
}
// ···
}
class SmartTelevision extends Television {
void turnOn() {
super.turnOn();
_bootNetworkInterface();
_initializeMemory();
_upgradeApps();
}
// ···
}
重寫(xiě)成員
子類(lèi)可以重寫(xiě)實(shí)例方法施禾、getters和setters脚线。您可以使用@override
注解來(lái)指示你想要重寫(xiě)的成員:
class SmartTelevision extends Television {
@override
void turnOn() {...}
// ···
}
要縮小代碼中類(lèi)型安全的方法參數(shù)或?qū)嵗兞康念?lèi)型,可以使用covariant
關(guān)鍵字弥搞。
重寫(xiě)運(yùn)算符
你可以重寫(xiě)以下表中顯示的運(yùn)算符邮绿。例如,如果定義Vecor類(lèi)攀例,則可以定義+
方法來(lái)添加兩個(gè)vectors船逮。
< | + | | | [] |
---|---|---|---|
> | / | ^ | []= |
<= | ~/ | & | ~ |
>= | * | << | == |
– | % | >> |
注意:你可能已經(jīng)注意到了
!=
不是可重寫(xiě)的運(yùn)算符。表達(dá)式E1粤铭!= E2
只是語(yǔ)法上的糖!( E1 = = E2 )
下面是一個(gè)重寫(xiě)+
和-
運(yùn)算符的類(lèi)的示例:
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);
//運(yùn)算符= =和hashCode未顯示挖胃。
}
void main() {
final v = Vector(2, 3);
final w = Vector(2, 2);
assert(v + w == Vector(4, 5));
assert(v - w == Vector(0, 1));
}
如果重寫(xiě)==
,則還應(yīng)該重寫(xiě)對(duì)象的hashCode
getter梆惯。
noSuchMethod()
要在代碼試圖使用不存在的方法或?qū)嵗兞繒r(shí)檢測(cè)或做出反應(yīng)酱鸭,可以重寫(xiě)noSuchMethod ( ) :
class A {
// 除非重寫(xiě)noSuchMethod,否則使用不存在的成員會(huì)導(dǎo)致noSuchMethod錯(cuò)誤垛吗。
@override
void noSuchMethod(Invocation invocation) {
print('You tried to use a non-existent member: ' +
'${invocation.memberName}');
}
}
除非下列情況之一成立凹髓,否則不能調(diào)用未實(shí)現(xiàn)的方法:
- 接收者具有靜態(tài)類(lèi)型
dynamic
。 - 接收者具有定義未實(shí)現(xiàn)方法的靜態(tài)類(lèi)型(抽象是可以的)怯屉,接收者的動(dòng)態(tài)類(lèi)型具有不同于類(lèi)
Object
中的noSuchMethod()
的實(shí)現(xiàn)蔚舀。
枚舉類(lèi)型
枚舉類(lèi)型,通常稱(chēng)為枚舉锨络,是一種特殊類(lèi)型的類(lèi)赌躺,用于表示固定數(shù)量的常量值。
使用枚舉
使用enum
關(guān)鍵詞來(lái)聲明一個(gè)枚舉類(lèi)型
enum Color { red, green, blue }
枚舉中的每個(gè)值都有一個(gè)index
索引足删,它返回枚舉聲明中值的從零開(kāi)始的位置寿谴。例如,第一個(gè)值具有索引0失受,第二個(gè)值具有索引1讶泰。
assert(Color.red.index == 0);
assert(Color.green.index == 1);
assert(Color.blue.index == 2);
若要獲取枚舉中所有值的列表咏瑟,請(qǐng)使用枚舉的values
常量。
List<Color> colors = Color.values;
assert(colors[2] == Color.blue);
你可以在switch語(yǔ)句中使用枚舉痪署,如果不處理枚舉的所有值码泞,將會(huì)收到警告:
var aColor = Color.blue;
switch (aColor) {
case Color.red:
print('Red as roses!');
break;
case Color.green:
print('Green as grass!');
break;
default: // 沒(méi)有default,將會(huì)報(bào)錯(cuò)
print(aColor); // 'Color.blue'
}
枚舉類(lèi)型有以下限制:
- 你不能子類(lèi)化、混合或?qū)崿F(xiàn)枚舉狼犯。
- 不能顯式實(shí)例化枚舉余寥。
給類(lèi)添加一個(gè)特性:混合(mixin)
混合(mixin)是一種在多個(gè)類(lèi)層次中重用類(lèi)代碼的方法。
若要使用mixin悯森,請(qǐng)使用with
關(guān)鍵字后跟一個(gè)或多個(gè)mixin名稱(chēng)宋舷。下面的示例顯示了使用mixins的兩個(gè)類(lèi):
class Musician extends Performer with Musical {
// ···
}
class Maestro extends Person
with Musical, Aggressive, Demented {
Maestro(String maestroName) {
name = maestroName;
canConduct = true;
}
}
要實(shí)現(xiàn)mixin,請(qǐng)創(chuàng)建一個(gè)擴(kuò)展對(duì)象的類(lèi)瓢姻,聲明沒(méi)有構(gòu)造函數(shù)祝蝠,也沒(méi)有對(duì)super
的調(diào)用。例如:
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');
}
}
}
注意:一些對(duì)mixin的限制正在被取消幻碱。有關(guān)詳細(xì)信息绎狭,請(qǐng)參見(jiàn)建議的mixin規(guī)范。
類(lèi)變量和類(lèi)方法
使用static
關(guān)鍵字實(shí)現(xiàn)類(lèi)范圍的變量和方法褥傍。
靜態(tài)變量
靜態(tài)變量(類(lèi)變量)對(duì)于類(lèi)范圍的狀態(tài)和常量非常有用:
靜態(tài)變量在使用之前不會(huì)初始化儡嘶。
靜態(tài)方法
靜態(tài)方法(類(lèi)方法)不能在實(shí)例操作,因此它沒(méi)有訪問(wèn)this
的權(quán)限恍风。例如:
import 'dart:math';
class Point {
num x, y;
Point(this.x, this.y);
static num distanceBetween(Point a, Point b) {
var dx = a.x - b.x;
var dy = a.y - b.y;
return sqrt(dx * dx + dy * dy);
}
}
void main() {
var a = Point(2, 2);
var b = Point(4, 4);
var distance = Point.distanceBetween(a, b);
assert(2.8 < distance && distance < 2.9);
print(distance);
}
注意:為了常用或廣泛使用的實(shí)用程序和功能蹦狂,考慮使用頂層函數(shù),而不是靜態(tài)方法邻耕。
可以使用靜態(tài)方法作為編譯時(shí)常量鸥咖。例如,可以將靜態(tài)方法作為參數(shù)傳遞給常量構(gòu)造函數(shù)兄世。
PS:本文
整理
自官方文檔啼辣,若有發(fā)現(xiàn)問(wèn)題請(qǐng)致郵 caoyanglee92@gmail.com