flutter開發(fā) dart類(四)

? Dart 是一個面向?qū)ο缶幊陶Z言。 每個對象都是一個類的實例,所有的類都繼承于 Object。

//每個實例變量都會自動生成一個 getter 方法(隱含的)。 非final 實例變量還會自動生成一個 setter 方法。
class Point {
  num x;
  num y;
}

構(gòu)造函數(shù)

? 由于把構(gòu)造函數(shù)參數(shù)賦值給實例變量的場景太常見了, Dart 提供了一個語法糖來簡化這個操作:

class Point {
  num x;
  num y;

  Point(this.x, this.y);
}

命名構(gòu)造函數(shù)

? Dart 并不支持構(gòu)造函數(shù)的重載,而采用了命名構(gòu)造函數(shù)為一個類實現(xiàn)多個構(gòu)造函數(shù):

class Point {
  num x;
  num y;
  Point(this.x, this.y);
  Point(this.y);///錯誤,不允許重載
  //命名構(gòu)造函數(shù)
  Point.y(this.y) {
    x = 0;
  }
}

//使用
var p = Point.y(0);

初始化列表

? 在構(gòu)造函數(shù)函數(shù)體執(zhí)行之前會首先執(zhí)行初始化列表,非常適合用來設(shè)置 final 變量的值。

class Point {
  num x;
  num y;
  Point(this.x, this.y);
  //命名構(gòu)造函數(shù)
  Point.y(this.y) {
    x = 0;
  }

  Point.fromMap(Map map)
      : x = map['x'], // : 和c++一樣,初始化列表
        y = map['y'];
  
  Point.x(int i)
      : x = i, 
        y = 0;
}

重定向構(gòu)造函數(shù)

? 有時候一個構(gòu)造函數(shù)會調(diào)動類中的其他構(gòu)造函數(shù)(在Java中就是 this(...))。 一個重定向構(gòu)造函數(shù)是沒有代碼的,在構(gòu)造函數(shù)聲明后,使用 冒號調(diào)用其他構(gòu)造函數(shù)。

class Point {
  num x;
  num y;

  Point(this.x, this.y);
  Point.xy(int x,int y):this(x,y); ///調(diào)用上面的構(gòu)造函數(shù)
}

常量構(gòu)造函數(shù)

? 如果你的類提供一個狀態(tài)不變的對象,你可以把這些對象 定義為編譯時常量。要實現(xiàn)這個功能,需要定義一個 const 構(gòu)造函數(shù), 并且聲明所有類的變量為 final

class ImmutablePoint {
  final num x;
  final num y;
  //常量構(gòu)造函數(shù)
  const ImmutablePoint(this.x, this.y);
}

void main(){
    //編譯器常量
    var p1 = const ImmutablePoint(0,0);
    var p2 = const ImmutablePoint(0,0);
    print(p1 == p2); // true
}

工廠構(gòu)造函數(shù)

? 當實現(xiàn)一個使用factory 關(guān)鍵詞修飾的構(gòu)造函數(shù)時,這個構(gòu)造函數(shù)不必創(chuàng)建類的新實例。例如,一個工廠構(gòu)造函數(shù) 可能從緩存中獲取一個實例并返回,或者 返回一個子類型的實例。(工廠構(gòu)造函數(shù)無法訪問 this

class Logger {
  final String name;
  //從緩存獲取對象
  static final Map _cache = {};
  //工廠構(gòu)造函數(shù),無法使用this變量
  factory Logger(String name) {
    if (_cache.containsKey(name)) {
      //工廠構(gòu)造函數(shù)需要返回 Logger 實例對象
      return _cache[name];
    } else {
      final logger = Logger._internal(name);
      _cache[name] = logger;
      return logger;
    }
  }
  //以 _ 開頭的函數(shù)、變量無法在庫外使用
  Logger._internal(this.name);
}

? 借助工廠構(gòu)造函數(shù)能夠?qū)崿F(xiàn)單例:

//使用工廠構(gòu)造實現(xiàn)單例
class Manager {
  static Manager _instance;
  //和static是一樣的, 區(qū)別是factory畢竟是構(gòu)造函數(shù),需要返回一個實例,而static是靜態(tài)方法。
  factory Manager.getInstance() {
    if (_instance == null) {
      _instance =  new Manager._internal();
    }
    return _instance;
  }

//  static Manager getInstance() {
//    if (_instance == null) {
//      _instance = new Manager._internal();
//    }
//    return _instance;
//  }
  Manager._internal();
}

Getters 和 Setters

? Dart中每個實例變量都隱含的具有一個 getter, 如果變量不是 final 的則還有一個 setter??梢酝ㄟ^實現(xiàn) getter 和 setter 來創(chuàng)建新的屬性, 使用 getset 關(guān)鍵字定義 getter 和 setter:

class Rect {
  num left;
  num top;
  num width;
  num height;

  Rect(this.left, this.top, this.width, this.height);

  //使用 get定義了一個 right 屬性
  num get right             => left + width;
  set right(num value)  => left = value - width;
}

void main() {
  var rect = Rect(0, 0, 10, 10);
  print(rect.right); //10
  rect.right = 15;
  print(rect.left);  //5
}

需要注意的是,在get與set中使用自身會導(dǎo)致Stack Overflow

可覆寫的操作符

? 把已經(jīng)定義的、有一定功能的操作符進行重新定義??梢灾匦露x的操作符有:

| < | + | | | [] |
| ---- | ---- | ---- | ----- |
| > | / | ^ | []= |
| <= | ~/ | & | ~ |
| >= | * | << | == |
| | % | >> | |

? 比如:List就重寫了 []

class Point {
  int x;
  int y;
  //返回值 參數(shù)隨你定義
  Point operator +(Point point) {
    return Point(x + point.x, y + point.y);
  }

  Point(this.x, this.y);
}

var p1 = Point(1, 1);
var p2 = p1 + Point(2, 2);
print(p2.x); ///3
print(p2.y); ///3

抽象類

? 使用 abstract 修飾符定義一個抽象類。抽象類中允許出現(xiàn)無方法體的方法

abstract class Parent {
  String name;
  void printName(); //抽象方法,不需要在方法前聲明 abstract
}

? 抽象類不能被實例化,除非定義工廠方法并返回子類。

abstract class Parent {
  String name;
  //默認構(gòu)造方法
  Parent(this.name);
  //工廠方法返回Child實例
  factory Parent.test(String name){
    return new Child(name);
  }
  void printName();
}
// extends 繼承抽象類
class Child extends Parent{
  Child(String name) : super(name);

  @override
  void printName() {
    print(name);
  }
}

void main() {
  var p = Parent.test("test");
  print(p.runtimeType); //輸出實際類型 Child
  p.printName();        
}

接口

? 與Java不同,Dart中沒有interface關(guān)鍵字,Dart中每個類都隱式的定義了一個包含所有實例成員的接口, 并且這個類實現(xiàn)了這個接口。如果你想 創(chuàng)建類 A 來支持 類 B 的 方法,而不想繼承 B 的實現(xiàn), 則類 A 應(yīng)該實現(xiàn) B 的接口。

class Listener{
  void onComplete(){}
  void onFailure(){}
}

class MyListsner implements Listener{
  MyListsner(){

  }
  @override
  void onComplete() {
  }

  @override
  void onFailure() {
  }
}

與繼承的區(qū)別在于:

1、單繼承,多實現(xiàn)。

2、繼承可以有選擇的重寫父類方法并且可以使用super,實現(xiàn)強制重新定義接口所有成員。

可調(diào)用的類

? 如果 Dart 類實現(xiàn)了 call() 函數(shù)則 可以當做方法來調(diào)用。

class Closure {
  call(String a, String b) => '$a $b!';
}

main() {
  var c = new Closure();
  var out = c("Hello","Dart");
  print(out);
}

混合mixins

? Mixins 是一種在多類繼承中重用 一個類代碼的方法。它的基本形式如下:

//被mixin(混入)的類不能有構(gòu)造函數(shù)
class A  {
  void a(){}
}
class B{
  void b(){}
}
class C with A,B{
  void c(){}
}

with后面跟著需要混入的類,被mixin(混入)的類不能有構(gòu)造函數(shù)。現(xiàn)在的 C擁有了三個方法(a、b與c)。假設(shè)A與B 存在相同的方法,以最右側(cè)的混入類為主,比如:

class A {
  String getMessage() => 'A';
}

class B {
  String getMessage() => 'B';
}
//
class AB with A, B {}

class BA  with B, A {}

void printMessage(obj) => print(obj.getMessage());

void main() {
  printMessage(AB()); //輸出 B
  printMessage(BA()); //輸出 A
}

繼承與mixins是兼容的

class A {
  String getMessage() => 'A';
}

class B {
  String getMessage() => 'B';
}
class P{
  String getMessage() => 'P';
}
class AB extends P with A, B {}

class BA extends P with B, A {}
//可以簡寫成:
//class AB = P with A, B;
//class BA = P with B, A;
void printMessage(obj) => print(obj.getMessage());

void main() {
  printMessage(AB()); //輸出 B
  printMessage(BA()); //輸出 A
}

? mixins彌補了接口和繼承的不足,繼承只能單繼承,而接口無法復(fù)用實現(xiàn),mixins卻可以多混入并且能利用到混入類的具體實現(xiàn):

abstract class Swimming{
    void swimming(){
        print("游泳");
    }
}

abstract class Jump{
    void jump(){
        print("跳躍");
    }
}

//只能單繼承,如果需要Jump,只能以implements的形式
class Test extends Swimming implements Jump{
    //實現(xiàn)接口
    void jump(){
        print("跳躍");
    }
}

//但是實際上,我們經(jīng)常不需要重新實現(xiàn)Jump方法,復(fù)用Jump所實現(xiàn)的jump方法就可以了
//這時使用混合能夠更加方便
class Test with Swimming, Jump {}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容