Dart學(xué)習(xí)-類(lèi)

Dart

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í)行順序如下:

  1. 初始值列表
  2. 超類(lèi)的無(wú)參構(gòu)造器
  3. 主類(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ò)使用getset關(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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市御滩,隨后出現(xiàn)的幾起案子鸥拧,更是在濱河造成了極大的恐慌,老刑警劉巖削解,帶你破解...
    沈念sama閱讀 211,561評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件富弦,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡氛驮,警方通過(guò)查閱死者的電腦和手機(jī)腕柜,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,218評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人盏缤,你說(shuō)我怎么就攤上這事砰蠢。” “怎么了唉铜?”我有些...
    開(kāi)封第一講書(shū)人閱讀 157,162評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵台舱,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我潭流,道長(zhǎng)竞惋,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,470評(píng)論 1 283
  • 正文 為了忘掉前任灰嫉,我火速辦了婚禮拆宛,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘讼撒。我一直安慰自己胰挑,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,550評(píng)論 6 385
  • 文/花漫 我一把揭開(kāi)白布椿肩。 她就那樣靜靜地躺著,像睡著了一般豺谈。 火紅的嫁衣襯著肌膚如雪郑象。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,806評(píng)論 1 290
  • 那天茬末,我揣著相機(jī)與錄音厂榛,去河邊找鬼。 笑死丽惭,一個(gè)胖子當(dāng)著我的面吹牛击奶,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播责掏,決...
    沈念sama閱讀 38,951評(píng)論 3 407
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼柜砾,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了换衬?” 一聲冷哼從身側(cè)響起痰驱,我...
    開(kāi)封第一講書(shū)人閱讀 37,712評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎瞳浦,沒(méi)想到半個(gè)月后担映,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,166評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡叫潦,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,510評(píng)論 2 327
  • 正文 我和宋清朗相戀三年蝇完,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,643評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡短蜕,死狀恐怖氢架,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情忿危,我是刑警寧澤达箍,帶...
    沈念sama閱讀 34,306評(píng)論 4 330
  • 正文 年R本政府宣布,位于F島的核電站铺厨,受9級(jí)特大地震影響缎玫,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜解滓,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,930評(píng)論 3 313
  • 文/蒙蒙 一赃磨、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧洼裤,春花似錦、人聲如沸腮鞍。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,745評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)吱瘩。三九已至使碾,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間祝懂,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,983評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工矢门, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人怜械。 一個(gè)月前我還...
    沈念sama閱讀 46,351評(píng)論 2 360
  • 正文 我出身青樓颅和,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親缕允。 傳聞我的和親對(duì)象是個(gè)殘疾皇子峡扩,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,509評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容