美文网首页
Dart基础3-类

Dart基础3-类

作者: 叶落清秋 | 来源:发表于2018-12-14 16:48 被阅读26次

    1 构造函数

    1. 不要键入初始化的形式
    2. 空的构造函数体使用;而不是{}
    3. 不要使用new
    4. 不要过多使用const
      上面的说法只是规范性,当然你用了也不影响
    class Point {
      num x, y;
      //默认构造函数,只存在一个
      Point(this.x, this.y);
    }
    void main() { 
      //不要使用new(即使使用并不报错,但并不推荐,因为已经弃用了)
      var p = Point(1,2);
    }
    

    1.1 默认构造函数

    1. 默认构造函数只能存在一个
    2. 无返回值
    3. 如类无构造函数,则会自动创建一个隐式的无参默认构造函数
      注意:是无构造函数,并非无默认构造函数
    class Point {
      num x, y;
      //无构造函数会创建一个默认的无参构造函数 即Point();
    }
    void main() {  
      Point p = Point();
    }
    

    1.2 命名构造函数

    可理解为默认构造函数的重载,可存在多个

    class Point {
      num x, y;
      //命名构造函数
      Point.temp(this.x, this.y);
      //:后是赋值
      Point.temp2(a,b): x=a,y=b;
    }
    
    void main() {  
      Point p = Point.temp(1, 2);
      Point p2 = Point.temp2(1,2);
      Point p3 = Point();  //错误,无无参默认构造函数
    }
    

    1.3 重定向构造函数

    重定向构造函数的主体为空,构造函数调用出现在冒号(:)之后

    class Point {
      num x, y;
      Point(this.x, this.y);
    
      Point.alongXAxis(num x) : this(x, 0);
      
      Point.alongXAxis2() : this.alongXAxis(0);
    }
    

    1.4 常量构造函数

    生成的对象不会改变,所有的属性都是final的

    class ImmutablePoint {
      static final ImmutablePoint origin =const ImmutablePoint(0, 0);
      final num x, y;
    
      const ImmutablePoint(this.x, this.y);
    }
    

    1.5 工厂构造函数

    工厂构造函数可以从缓存返回实例,也可以返回子类型的实例

    1. factory修饰上述构造函数 , 修饰后需要返回值,返回本类类型
    2. 内部不能使用this
    class Logger {
      final String name;
      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);
    }
    

    2 setter和getter

    当定义一个属性时,会自动创建隐式的setter和getter方法,当属性被final或const修饰时,只会创建getter方法

    class Box {
      num get contents => contents*2;   //错误,会重复回调,get中不能再次使用contents
          set contents(value) {
            contents = value - 1;
          }
          
       num get single => 0;   //只定义get方法,是没有set方法的,效果等同于final(优点在于,在抽象类中,这种属性可以将属性的值延迟定义在子类实现中) 
    }
    //使用
    void main() { 
      var b = Box();
      b.contents;       //调用get方法
      b.contents = 2;   //调用set方法
    }
    

    3 继承extends

    继承类只能有一个

    方法继承

    class 继承后方法和属性可重写

    abstract class 继承后,其中的抽象方法必须重写(@override

    mixin 不可继承


    构造函数继承

    1. 继承默认无参构造函数时,可以省略
    2. 重定向继承的构造函数不能有实体
    3. 可随意继承,不必对应
    4. 先调用父类,再调用子类构造函数
    class B{
      int x;
      B(this.x){
        print("B $x");
      }
      B.mm(){
        print("B.mm");
      }
    }
    
    class T extends  B{
      T(int x): super(x){    //如果super无参数则可以省略
        print("T $x");
      }
      //命名构造函数的继承方式与默认构造函数是一样的
      T.mm(): super(1){
        print("T.mm");
      }
      T.nn(): super.mm(){
          print("T.mm");
      }
      T.aa():this.nn();   //重定向构造函数,不能有实体
    }
    
    void main() {
      T t = T(1);  //先打印B 1 ,在打印T 1
    }
    

    4 实现implements

    1. 实现的接口可存在多个
    2. dart不存在interface, 上面3类型都可实现
    3. 方法都必须重写实现(不会使用接口的方法)
    4. 属性都必须实现(setter/getter,final只需要getter),向上兼容,且值并不会传递过来
    class A{
      void b(){
        print("A.b");
      }
    }
    
    abstract class B{
      final int x =1;
      int y = 1;
      void b();
    }
    
    class T extends  A implements B{
      //重写x属性,这里扩展了方法setter。
      @override
      int x = 2;   //向上兼容,反之错误
      //final int y = 2;   //错误,将y属性已经存在的setter方法去掉并不合理
      void printX(){
        print("T.x $x"); //打印T.x 2
      }
    }
    
    void main() {
      T().b();
    }
    

    5 混合with

    这个概念,主要是解决无法继承多个父类的问题

    但是,引入多个父类的话,会造成方法和属性重复,这时就要靠with决定

    //A中的方法和属性为A和S方法的集合,如果有重复,取S中的
    class T = A with S;
    //多个就顺序混合,即 (A with B)with S
    class T2 = A with B,S;
    //顺序混合,即 (A with C)with S
    class T3 with A,C,S{}
    

    混合是顺序的,类似于贴纸,最后贴的保存使用
    关于super
    T2中的S内使用super,那么调用的将是A with B内的方法或属性,是层级结构的
    注意:用于混合的类不能声明构造函数

    class S {
      int x = 1;
      a() {print("S.a");}
      //S();  声明构造函数就不能用于混合
    }
    
    class A {
      int x = 2;
      a(){print("A.a");}
      b(){print("A.b");}
    }
    
    class B {
      int x = 3;
      a(){print("B.a");}
      b(){print("B.b");}
      c(){print("B.c $x");}  //S在最末,所以x的值去S中的x
    }
    
    mixin C{}
    //mixin的继承方式使用on(只能一个父类)
    mixin C2 on A{}
    ////mixin的实现方式使用implements(可以多个接口)
    mixin C3 on A implements B,S{}
    
    //方式一
    class T = B with A, S;
    //方式二,可加入新的方法
    class T2 extends B with A, S{
        //方法重写,优先级最高
        a(){print("T2.a");}
    }
    //方式三,可直接混合
    class T3 with A,C,S{
        
    }
    
    void main() {
      T t = T();
      //打印顺序为:S.a    A.b      B.c 3
      t.a();
      t.b();
      t.c();
    }
    
    

    6 可调用的类

    实现call()方法可以让你的Dart类像函数一样被调用

    class WannabeFunction {
      call(String a, String b, String c) => '$a $b $c!';
    }
    
    main() {
      var wf = new WannabeFunction();
      var out = wf("Hi", "there,", "gang");
      print('$out');
    }
    

    7 元数据

    元数据即javaannotation注解,但本质是一个常量构造函数

    class Todo {
      final String who;
      final String what;
    
      const Todo(this.who, this.what);
    }
    
    @Todo('seth', 'make this do something')
    void doSomething() {
      print('do something');
    }
    

    元数据可以出现在库、类、类型定义、类型参数、构造函数、工厂、函数、字段、参数或变量声明之前,也可以出现在导入或导出指令之前

    元数据可配合反射(mirrors)使用

    相关文章

      网友评论

          本文标题:Dart基础3-类

          本文链接:https://www.haomeiwen.com/subject/grvghqtx.html