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

新公司迭代需求有點(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)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

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