美文网首页
dart语言学习笔记-3

dart语言学习笔记-3

作者: fan_xing | 来源:发表于2019-03-08 15:38 被阅读0次

    类-class

    1. 若类提供了constant的构造方法,需要考虑重复构建的结果为同一对象
    void main() {
      var a = const ImmutablePoint(1, 1);
        var b = const ImmutablePoint(1, 1);
    
        print(identical(a, b)); // They are the same instance!
    }
    
    class ImmutablePoint {
      static final ImmutablePoint origin =
          const ImmutablePoint(0, 0);
    
      final num x, y;
    
      const ImmutablePoint(this.x, this.y);
    }
    
    1. 通过runtimeType获取对象的类
    print('The type of a is ${a.runtimeType}');
    
    1. 所有的实例对象会隐式的生成getter方法,非final的实例会生成setter方法。
      如果变量在声明的时候进行了初始化(不是通过构造器或者方法),那么变量的值会先于构造器和他本身的初始化列表之前创建(If you initialize an instance variable where it is declared (instead of in a constructor or method), the value is set when the instance is created, which is before the constructor and its initializer list execute.)
    class Point {
      num x;
      num y;
    }
    
    void main() {
      var point = Point();
      point.x = 4; // Use the setter method for x.
      assert(point.x == 4); // Use the getter method for x.
      assert(point.y == null); // Values default to null.
    }
    
    1. constructor
      4.1. Dart提供语法糖来简化构造器的参数传递
    class Point {
      num x, y;
    
      Point(num x, num y) {
        // There's a better way to do this, stay tuned.
        this.x = x;
        this.y = y;
      }
    }
    
    class Point {
      num x, y;
    
      // Syntactic sugar for setting x and y
      // before the constructor body runs.
      Point(this.x, this.y);
    }
    

    4.2. 构造器并不会继承
    如果不存在构造器,Dart会默认提供一个无参的构造器。并且默认的构造器会调用父类的无参构造器。
    子类不会继承父类的构造器,如果子类没有声明构造器,那么Dart只会为其包含默认的构造器(无参,无名的)。
    4.3. 给构造器命名
    目的是提供多形态的意义明确的构造器

    class Point {
      num x, y;
    
      Point(this.x, this.y);
    
      // Named constructor
      Point.origin() {
        x = 0;
        y = 0;
      }
    }
    

    4.4. 初始化列表

    // Initializer list sets instance variables before
    // the constructor body runs.
    Point.fromJson(Map<String, num> json)
        : x = json['x'],
          y = json['y'] {
      print('In Point.fromJson(): ($x, $y)');
    }
    

    4.5. 调用非默认的父构造器
    默认情况下,子类会调用父类的无参且无名的构造器,执行顺序为
    a. 初始化列表
    b. 父类的无参构造器
    c. 子类的无参构造器
    如果父类有定义构造器,子类必须调用父类的构造器,格式如下

    class Person {
      String firstName;
    
      Person.fromJson(Map data) {
        print('in Person');
      }
    }
    
    class Employee extends Person {
      // Person does not have a default constructor;
      // you must call super.fromJson(data).
      Employee.fromJson(Map data) : super.fromJson(data) {
        print('in Employee');
      }
    }
    
    main() {
      var emp = new Employee.fromJson({});
    
      // Prints:
      // in Person
      // in Employee
      if (emp is Person) {
        // Type check
        emp.firstName = 'Bob';
      }
      (emp as Person).firstName = 'Bob';
    }
    

    注:传递给父构造器的参数在调用父构造器前,所以也参数也可以是表达式

    class Employee extends Person {
      Employee() : super.fromJson(getDefaultData());
      // ···
    }
    

    4.6. 重定向

    class Point {
      num x, y;
    
      // The main constructor for this class.
      Point(this.x, this.y);
    
      // Delegates to the main constructor.
      Point.alongXAxis(num x) : this(x, 0);
    }
    

    4.7. constant构造器
    如果你希望类的实例永不改变,就让他的实例成为编译期常量,通过const构造器并将成员变量设置为final即可

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

    注:constant的构造器并不一定创建常量
    4.8. Factory构造器
    通过关键字factory,使用方式同一般的构造器

    class Logger {
      final String name;
      bool mute = false;
    
      // _cache is library-private, thanks to
      // the _ in front of its 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);
    
      void log(String msg) {
        if (!mute) print(msg);
      }
    }
    
    var logger = Logger('UI');
    logger.log('Button clicked');
    
    1. 方法-Methods
      5.1. getters & setters
      Dart默认情况下会生成getter/setter方法,也可以通过get/set关键字定义方法
    class Rectangle {
      num left, top, width, height;
    
      Rectangle(this.left, this.top, this.width, this.height);
    
      // Define two calculated properties: right and bottom.
      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);
    }
    

    注:定义的getter/setter避免在某些操作符下的歧义,如++,会先调用一次getter,然后调用一次setter
    5.2. 抽象类-abstract

    // This class is declared abstract and thus
    // can't be instantiated.
    abstract class AbstractContainer {
      // Define constructors, fields, methods...
    
      void updateChildren(); // Abstract method.
    }
    

    5.3. 隐式接口-implicit interfaces
    所有的类都隐式的定义了一个接口,该接口包含他自身的成员和他所继承的接口的成员。如果A想不通过继承B来支持B的API,A就要实现B的接口。通过关键字implements实现接口,多个接口间逗号分隔。

    import 'dart:math';
    
    void main() {
      print(greetBob(Person('Kathy')));
      print(greetBob(Impostor()));
    }
    
    class Person {
      final _name;
      
      Person(this._name);
      
      String greet(String who) => 'Hello, $who, i am $_name.';
    }
    
    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');
    
    1. 类的继承
      用关键字extends,super关键字来引用父类
    2. 可复写的操作符


      image.png
    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);
    
      // Operator == and hashCode not shown. For details, see note below.
      // ···
    }
    
    void main() {
      final v = Vector(2, 3);
      final w = Vector(2, 2);
    
      assert(v + w == Vector(4, 5));
      assert(v - w == Vector(0, 1));
    }
    

    如果复写了==,则相应的hashCode也要复写

    1. noSuchMethod()
      当调用不存在的方法或变量时,可通过noSuchMethod进行监测。
    void main() {
      dynamic a = A();
      //打印:You tried to use a non-existent member: Symbol("say")
      a.say();
    }
    
    class A {
      // Unless you override noSuchMethod, using a
      // non-existent member results in a NoSuchMethodError.
      @override
      void noSuchMethod(Invocation invocation) {
        print('You tried to use a non-existent member: ' +
            '${invocation.memberName}');
      }
    }
    

    你不能直接调用未包含的方法,除非以下情况:
    a. dynamic定义的调用接收方
    b. 调用接收方为静态类,定义了未实现的方法(如抽象类),并实现了noSuchMethod方法

    枚举-enum

    枚举的成员都有一个index的getter,从0开始

    enum Color { red, green, blue }
    
    assert(Color.red.index == 0);
    assert(Color.green.index == 1);
    assert(Color.blue.index == 2);
    

    通过values转为list集合

    List<Color> colors = Color.values;
    assert(colors[2] == Color.blue);
    

    枚举的限制:

    1. 不能被继承,混入
    2. 不能被实例化

    通过混入来增强类

    混入是通过类的代码重用来达到多重继承的效果,

    通过关键字with,来使用混入
    class Musician extends Performer with Musical {
      // ···
    }
    
    class Maestro extends Person
        with Musical, Aggressive, Demented {
      Maestro(String maestroName) {
        name = maestroName;
        canConduct = true;
      }
    }
    
    通过关键字mixin来定义混入

    用mixin来定义一个继承自Object并没有声明构造器的类。如果你想此类可以像一般的类一样使用,那么用class替换mixin来定义。

    mixin 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');
        }
      }
    }
    
    如果想约束混入的使用,通过on来明确具体的父类
    mixin MusicalPerformer on Musician {
      // ···
    }
    

    相关文章

      网友评论

          本文标题:dart语言学习笔记-3

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