03 - Dart筆記-面向?qū)ο?/h1>

新公司迭代需求有點(diǎn)猛,拖了很長(zhǎng)時(shí)間。
計(jì)劃Dart還有一篇高級(jí)特性的筆記

[TOC]

類(lèi)的使用

通過(guò)構(gòu)造函數(shù)實(shí)例化

// 非 命名構(gòu)造函數(shù)
var test = Test();
  
// 命名構(gòu)造函數(shù)(named ctor)
var testFeature = TestFeature.fromTest(test);
// 常量構(gòu)造函數(shù)
var constObj1 = const TestConstCtor(1);

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

  • const構(gòu)造函數(shù)必須用于成員變量都是final的類(lèi)
  • 構(gòu)建常量實(shí)例必須使用定義的常量構(gòu)造函數(shù)枷餐,如果不是常量構(gòu)造函數(shù)是無(wú)法在實(shí)例化時(shí)使用const修飾符
  • 如果實(shí)例化時(shí)不加const修飾符,即使調(diào)用的是聲明為const的構(gòu)造函數(shù),實(shí)例化的也不是常量實(shí)例
class TestConstCtor {
  final int x;
  // const構(gòu)造函數(shù)必須用于成員變量都是final的類(lèi)
  // Can't define a constructor for a class with non-final fields
//  String y;
  const TestConstCtor(this.x);
}

void testConstCtor() {

  // 構(gòu)建常量實(shí)例必須使用定義的常量構(gòu)造函數(shù)且轨,如果不是常量構(gòu)造函數(shù)是無(wú)法在實(shí)例化時(shí)使用const修飾符
  // The constructor being called isn't a const constructor
  //  var test2 = const Test();
  var constObj1 = const TestConstCtor(1);
  var constObj2 = const TestConstCtor(2);
  var constObj2_2 = const TestConstCtor(2);
  // 如果實(shí)例化時(shí)不加const修飾符,即使調(diào)用的是聲明為const的構(gòu)造函數(shù)虚婿,實(shí)例化的也不是常量實(shí)例
  var constObj2_3 = TestConstCtor(2);

  print("const TestConstCtor(1) and const TestConstCtor(2) same: ${identical
    (constObj1, constObj2)}"); //false

  print("const TestConstCtor(2) and const TestConstCtor(2) same: ${identical
    (constObj2_2, constObj2)}");//true

  print("TestConstCtor(2) and const TestConstCtor(2) same: ${identical
    (constObj2_2,constObj2_3)}");//false
}

對(duì)象的運(yùn)行時(shí)類(lèi)型

obj.runtimeType返回的是對(duì)象的實(shí)際類(lèi)型旋奢,即使根據(jù)多態(tài)的特性將變量聲明為父類(lèi)類(lèi)型,runtimeType也會(huì)返回實(shí)際類(lèi)型

setter/getter

  • 類(lèi)的成員變量默認(rèn)生成與字段同名的set/get函數(shù)

  • 字面意義上的私有成員變量也會(huì)生成set/get函數(shù)然痊,在類(lèi)的外部可以調(diào)用

    class TestFeature {
      int c;
      int d;
    
      int _f;
      // ...
    }
    
    test(){
        var testFeature = TestFeature.fromTest(test);
        testFeature._f = 20;
        print("_f = ${testFeature._f}");
    }
    

    ?

  • 計(jì)算屬性的set/get

    <type> get <computedProperty> {
        
    }
    set <computedProperty>(<type> value) {
        
    }
    

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

警告:初始化器的右邊部分中無(wú)法訪問(wèn)this關(guān)鍵字至朗。

默認(rèn)構(gòu)造函數(shù)

  • 不聲明構(gòu)造函數(shù)則提供默認(rèn)構(gòu)造函數(shù)
  • 只要有構(gòu)造函數(shù),即使是命名構(gòu)造函數(shù)剧浸,就不會(huì)提供默認(rèn)的構(gòu)造函數(shù)
  • 無(wú)參數(shù)锹引,非命名
void testDef() {
  // 只要有構(gòu)造函數(shù),即使是命名構(gòu)造函數(shù)唆香,就不會(huì)提供默認(rèn)的構(gòu)造函數(shù)
  // The class 'TestDefault' doesn't have a default constructor
//  var testDefault = TestDefault();
}

class TestDefault {
  int a;
  int b;

//  TestDefault();
  TestDefault.namedCtor(int c) {
    a = c;
    b = c;
  }
}

帶參數(shù)的非命名構(gòu)造函數(shù)

  • 直接給類(lèi)成員變量賦值的語(yǔ)法糖

    class Test {
        int a;
        Test(this.a);
    }
    
  • 構(gòu)造函數(shù)的參數(shù)列表與普通函數(shù)相同嫌变,可以處理無(wú)參,必須參數(shù)和可選參數(shù)等不同的情況

    class TestNotNamed {
      int c;
      int d;
      int e;
      int f;
      
    //  TestNotNamed();
    //  TestNotNamed(this.d);
    //  TestNotNamed(this.c, {this.d, this.e, this.f});
    //  TestNotNamed(this.c, [this.d, this.e, this.f]);
    
      TestNotNamed(int x, int y) {
        c = x + y;
      }
    
    }
    

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

使用命名構(gòu)造函數(shù)可以在一個(gè)類(lèi)中定義多個(gè)構(gòu)造函數(shù)躬它,不同的命名構(gòu)造函數(shù)可以專(zhuān)門(mén)用于不同的場(chǎng)景:

class Point {
  num x, y;

  Point(this.x, this.y);

  // Named constructor
  Point.origin() {
    x = 0;
    y = 0;
  }
}

構(gòu)造函數(shù)沒(méi)有繼承

  • 子類(lèi)不從父類(lèi)繼承構(gòu)造函數(shù)腾啥。
  • 如果父類(lèi)有默認(rèn)構(gòu)造函數(shù),則子類(lèi)任意定義構(gòu)造函數(shù),默認(rèn)會(huì)調(diào)用執(zhí)行父類(lèi)的默認(rèn)構(gòu)造函數(shù)碑宴,不必強(qiáng)制使用初始化器列表調(diào)用父類(lèi)的構(gòu)造函數(shù)
  • 父類(lèi)沒(méi)有提供默認(rèn)構(gòu)造函數(shù)软啼,子類(lèi)須要顯示指定使用父類(lèi)的哪一個(gè)構(gòu)造函數(shù),并傳遞參數(shù)
class TestParent {
  int m;

  TestParent.noArg();
}

class TestChild extends TestParent {
  int x;

  // 不顯示定義構(gòu)造函數(shù)則報(bào)錯(cuò)
//  TestChild() :super.noArg();
  TestChild.noArg() : super.noArg();
}

構(gòu)造函數(shù)的初始化器

初始化器在構(gòu)造函數(shù)聲明和方法體中間延柠。

構(gòu)造函數(shù)向初始化器傳遞參數(shù)

不需要使用this區(qū)分入?yún)⒑皖?lèi)的成員變量

Square(int id, int width, int height)
      : super(id, width: width, height: height);

Square.bySize(int id, int size) : super(id, width: size, height: size);

super調(diào)用父類(lèi)構(gòu)造函數(shù)

  • 父類(lèi)構(gòu)造函數(shù)初始化器必須是初始化器列表的最后一項(xiàng)
Square(int id, int width, int height)
    : super(id, width: width, height: height);

Square.testInitList(int id)
      : desc = "it's a desc",
        // 重定向構(gòu)造函數(shù)初始化器必須單獨(dú)使用祸挪,不能和域初始化器和父類(lèi)構(gòu)造函數(shù)初始化器同時(shí)使用
        // The redirecting constructor can't have a field initializer
//        this.bySize(id,10),
        super(id)
  // 父類(lèi)構(gòu)造函數(shù)初始化器必須是初始化器列表的最后一項(xiàng)
  // super call must be last in initializer list
//      ,comment = "a new comment"
  ;

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

  • 重定向構(gòu)造函數(shù)初始化器必須單獨(dú)使用,不能和域初始化器和父類(lèi)構(gòu)造函數(shù)初始化器同時(shí)使用
  Rectangle.twiceWidth(int id, int width)
      // 構(gòu)造函數(shù)重定向
      // 初始化器不能使用this贞间,也就是只能使用頂層函數(shù)和static靜態(tài)函數(shù)
      : this(id, width: width, height: getTwiceWidth(width));

Square.testInitList(int id)
      : desc = "it's a desc",
        // 重定向構(gòu)造函數(shù)初始化器必須單獨(dú)使用贿条,不能和域初始化器和父類(lèi)構(gòu)造函數(shù)初始化器同時(shí)使用
        // The redirecting constructor can't have a field initializer
//        this.bySize(id,10)

初始化實(shí)例變量

class Square extends Rectangle {
    String comment;
    // ...
    Square.initMember()
      :comment="a comment",
        super(1);
}

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

  • 構(gòu)造函數(shù)前使用factory關(guān)鍵字標(biāo)識(shí)其是工廠構(gòu)造函數(shù)
  • factory 聲明的工廠構(gòu)造函數(shù)不能使用this關(guān)鍵字,這種構(gòu)造函數(shù)類(lèi)似static靜態(tài)函數(shù)
class TestFactory {
  final String factoryName;

  static final Map<String, TestFactory> _cache = <String, TestFactory>{};

  TestFactory._internal(this.factoryName);

  // factory 聲明的工廠構(gòu)造函數(shù)不能使用this關(guān)鍵字增热,這種構(gòu)造函數(shù)類(lèi)似static靜態(tài)函數(shù)
  // Initializing formal parameters can't be used in factory constructors.
//  factory TestFactory(this.factoryName);

  factory TestFactory(String factoryName) {
    var instance = _cache[factoryName];
    if (null == instance) {
      instance = TestFactory._internal(factoryName);
      _cache[factoryName] = instance;
      return instance;
    } else {
      return instance;
    }
  }

}

類(lèi)的特性

類(lèi)的實(shí)例方法/set/get/計(jì)算屬性

  • set/get默認(rèn)實(shí)現(xiàn)整以,不需要顯式聲明和實(shí)現(xiàn)

  • 如果需要處理set/get,按照特定格式聲明set/get

    <type> get <property> {
        
    }
    
    // 顯式定義setter時(shí)避免設(shè)置返回類(lèi)型
    // avoid return type on setters
    /*void*/ set <property>(<params>) {
        
    }
    
  • 可以通過(guò)set/get設(shè)置計(jì)算屬性峻仇。但是與Vue不同公黑,調(diào)用計(jì)算屬性的get仍然每次都會(huì)執(zhí)行計(jì)算

    class TestMethod {
      int a;
      int b;
      int c;
      int d;
    
      TestMethod(this.a, this.b, this.c, this.d);
    
      int get e {
        // 計(jì)算屬性在執(zhí)行g(shù)etter方法時(shí)每次都會(huì)執(zhí)行statement,與Vue的計(jì)算屬性不同
        print("get e");
        int ret = a + b;
        return ret;
      }
    
      // 顯式定義setter時(shí)避免設(shè)置返回類(lèi)型
      // avoid return type on setters
      /*void*/
      set e(int vi) {
        a = vi - b;
      }
    }
    

    ?

抽象類(lèi)與抽象方法摄咆、隱式接口

  • 抽象類(lèi)不能(用new)實(shí)例化
  • 每個(gè)類(lèi)都提供一個(gè)同名的凡蚜,包含所有方法的隱式接口
  • 接口類(lèi)的聲明使用abstract class XXX
  • set/get 也可以聲明為abstract交由子類(lèi)具體實(shí)現(xiàn)
abstract class TestAbstract {
  void methodA() => print("real method");

  void abstractMethod(String text);

  int a;

  int get abstractGet;

  set abstractSet(int value);
}

class TestAbstractImpl extends TestAbstract {
  @override
  // TODO: implement abstractGet
  int get abstractGet => null;

  @override
  void abstractMethod(String text) {
    // TODO: implement abstractMethod
  }

  @override
  void set abstractSet(int value) {
    // TODO: implement abstractSet
  }

//  noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
}

class TestInterface {
  void saySth(String text) {
    print(text);
  }
}

class TestInterfaceImpl implements TestInterface {
  @override
  void saySth(String text) {
    // TODO: implement saySth
  }
}

操作符override

  • 函數(shù)名為操作符,函數(shù)名前使用operator標(biāo)識(shí) <returnType> operator <op>(<params>) {}
  • 支持的操作符
< + | []
> / ^ []=
<= ~/ & ~
>= * << ==
- % >>
class TestOverrideOperator {
  int a;
  int b;

  TestOverrideOperator(this.a, this.b);

  TestOverrideOperator operator +(TestOverrideOperator opVal) =>
      TestOverrideOperator(this.a + opVal.a, this.b + opVal.b);

  @override
  String toString() {
    return 'TestOverrideOperator{a: $a, b: $b}';
  }
}

noSuchMethod

重寫(xiě)noSuchMethod()方法來(lái)處理程序訪問(wèn)一個(gè)不存在的方法或者成員變量

class Foo {
  void sayHi() => print("hi");

  int get money => 123;
}

class TestNoSuchMethod implements Foo {
  void hello() => print("hello");

  int get salary => 777;

  @override
  noSuchMethod(Invocation invocation) {
    var runtimeType = invocation.runtimeType;
    // invocation.memberName 返回的是Symbol對(duì)象吭从,
    // #操作符 用于引用一個(gè)操作符(方法名)
    if (invocation.memberName == #sayHi) {
      if (invocation.isMethod) {
        return hello();
      }
    } else if (invocation.memberName == #money) {
      if (invocation.isGetter) {
        // 如果調(diào)用的是get/set方法朝蜘,應(yīng)當(dāng)返回一個(gè)get/set方法的返回值
//        return hello;
        return salary;
      }
    }
    return super.noSuchMethod(invocation);
  }
}

mixin多繼承

  • 子類(lèi)使用with標(biāo)識(shí)符聲明其他繼承
  • Mixin類(lèi)必須是Object的直接子類(lèi)
  • Mixin類(lèi)不能聲明構(gòu)造函數(shù)
  • Mixin類(lèi)中不能出現(xiàn)super語(yǔ)句
class TestMixin extends Parent with MixinA {
  String b;
}

class Parent {
  int a;
}

class MixinA {
  int c;

//  MixinA(this.c);

  void play(String text) {
    print(text);
//    super.toString();
  }
}

枚舉

  • 枚舉的values下標(biāo)從0開(kāi)始
  • <type>.values返回所有的枚舉值
  • enum 使用switch必須把所有枚舉都列出,否則報(bào)錯(cuò)
void testEnum() {
  // 獲取所有的枚舉值
  var values = TestEum.values;
  // 枚舉的values下標(biāo)從0開(kāi)始
  var index2 = TestEum.TypeTwo.index;
  print("values:${values};index2:${index2}");

  var type = TestEum.TypeThree;

  // enum 使用switch必須把所有枚舉都列出涩金,否則報(bào)錯(cuò)
  switch (type) {
    case TestEum.TypeOne:
      break;
    case TestEum.TypeTwo:
      break;
    case TestEum.TypeThree:
      break;
  }
}

enum TestEum { TypeOne, TypeTwo, TypeThree }

泛型

  • 與java寫(xiě)法類(lèi)似谱醇,可以在類(lèi)上和方法上使用泛型
  • 運(yùn)行時(shí)不會(huì)泛型擦除
  • 泛型標(biāo)記不能實(shí)例化
void testGenericClass() {
  TestGeneric<MyImplA>(MyImplA(3, 5)).printDataName();
  TestGeneric<MyImplB>(MyImplB(41, 8)).printDataName();
}

class TestGeneric<T extends MyInterface> {
  final T data;

  TestGeneric(this.data);

  void printDataName() {
    print("for ${T}:name=${data.getName()}");
  }

// 泛型S不能實(shí)例化
//  S newInstance<S extends String>(String message) {
//    return new S(message);
//  }
}

abstract class MyInterface {
  String getName();
}

class MyImplA implements MyInterface {
  int a;
  int b;

  MyImplA(this.a, this.b);

  @override
  String getName() {
    return (a + b).toString();
  }
}

class MyImplB implements MyInterface {
  int c;
  int d;

  MyImplB(this.c, this.d);

  @override
  String getName() {
    return (c * d).toString();
  }
}

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者

  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市步做,隨后出現(xiàn)的幾起案子副渴,更是在濱河造成了極大的恐慌,老刑警劉巖辆床,帶你破解...
    沈念sama閱讀 206,378評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件佳晶,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡讼载,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén)中跌,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)咨堤,“玉大人,你說(shuō)我怎么就攤上這事漩符∫淮” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,702評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)凸克。 經(jīng)常有香客問(wèn)我议蟆,道長(zhǎng),這世上最難降的妖魔是什么萎战? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,259評(píng)論 1 279
  • 正文 為了忘掉前任咐容,我火速辦了婚禮,結(jié)果婚禮上蚂维,老公的妹妹穿的比我還像新娘戳粒。我一直安慰自己,他們只是感情好虫啥,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,263評(píng)論 5 371
  • 文/花漫 我一把揭開(kāi)白布蔚约。 她就那樣靜靜地躺著,像睡著了一般涂籽。 火紅的嫁衣襯著肌膚如雪苹祟。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,036評(píng)論 1 285
  • 那天评雌,我揣著相機(jī)與錄音树枫,去河邊找鬼。 笑死柳骄,一個(gè)胖子當(dāng)著我的面吹牛团赏,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播耐薯,決...
    沈念sama閱讀 38,349評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼舔清,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了曲初?” 一聲冷哼從身側(cè)響起体谒,我...
    開(kāi)封第一講書(shū)人閱讀 36,979評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎臼婆,沒(méi)想到半個(gè)月后抒痒,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,469評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡颁褂,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,938評(píng)論 2 323
  • 正文 我和宋清朗相戀三年故响,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片颁独。...
    茶點(diǎn)故事閱讀 38,059評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡彩届,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出誓酒,到底是詐尸還是另有隱情樟蠕,我是刑警寧澤,帶...
    沈念sama閱讀 33,703評(píng)論 4 323
  • 正文 年R本政府宣布,位于F島的核電站寨辩,受9級(jí)特大地震影響吓懈,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜靡狞,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,257評(píng)論 3 307
  • 文/蒙蒙 一耻警、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧耍攘,春花似錦榕栏、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,262評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至式曲,卻和暖如春妨托,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背吝羞。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,485評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工兰伤, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人钧排。 一個(gè)月前我還...
    沈念sama閱讀 45,501評(píng)論 2 354
  • 正文 我出身青樓敦腔,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親恨溜。 傳聞我的和親對(duì)象是個(gè)殘疾皇子符衔,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,792評(píng)論 2 345

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