美文网首页Dart
Dart - 类(方法、接口、继承)

Dart - 类(方法、接口、继承)

作者: LouisXWB | 来源:发表于2020-01-01 21:33 被阅读0次

    方法

    方法是对象提供行为的函数。

    Getter 和 Setter

    Getter 和 Setter 是一对用来读写对象属性的特殊方法,上面说过实例对象的每一个属性都有一个隐式的 Getter 方法,如果为非 final 属性的话还会有一个 Setter 方法,你可以使用 get 和 set 关键字为额外的属性添加 Getter 和 Setter 方法:

    class Rectangle {
      num left, top, width, height;
    
      Rectangle(this.left, this.top, this.width, this.height);
    
      // 定义两个计算产生的属性:right 和 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 方法都会正确地执行。为了避免一些不必要的异常情况,运算符只会调用 Getter 一次,然后将其值存储在一个临时变量中。

    抽象方法

    实例方法、Getter 方法以及 Setter 方法都可以是抽象的,定义一个接口方法而不去做具体的实现让实现它的类去实现该方法,抽象方法只能存在于抽象类中,抽象类的定义跟Java的抽象类类似,就不单独介绍了。

    abstract class Doer {
      // 定义实例变量和方法等等……
    
      void doSomething(); // 定义一个抽象方法。
    }
    
    class EffectiveDoer extends Doer {
      void doSomething() {
        // 提供一个实现,所以在这里该方法不再是抽象的……
      }
    }
    

    接口

    Dart 没有像 Java 用单独的关键字 interface 来定义接口,普通用 class 声明的类就可以是接口,可以通过关键字 implements来实现一个或多个接口并实现每个接口定义的 API:

    // A person. The implicit interface contains greet().
    // Person 类的隐式接口中包含 greet() 方法。
    class Person {
      // _name 变量同样包含在接口中,但它只是库内可见的。
      final _name;
    
      // 构造函数不在接口中。
      Person(this._name);
    
      // greet() 方法在接口中。
      String greet(String who) => '你好,$who。我是$_name。';
    }
    
    // Person 接口的一个实现。
    class Impostor implements Person {
      get _name => '';
    
      String greet(String who) => '你好$who。你知道我是谁吗?';
    }
    
    String greetBob(Person person) => person.greet('小芳');
    
    void main() {
      print(greetBob(Person('小芸')));
      print(greetBob(Impostor()));
    }
    

    这时疑问来了,接口跟继承有什么区别,不就是多继承吗?
    接口的实现则意味着,子类获取到的仅仅是接口的成员变量符号和方法符号,需要重新实现成员变量,以及方法的声明和初始化,否则编译器会报错。而继承可以选择不重新实现,这是最大的区别。

    看以下的例子:

    
    class Point {
      num x = 0, y = 0;
      void printInfo() => print('($x,$y)');
    }
    
    //Vector继承自Point
    class Vector extends Point{
      num z = 0;
      @override
      void printInfo() => print('($x,$y,$z)'); //覆写了printInfo实现
    }
    
    //Coordinate是对Point的接口实现
    class Coordinate implements Point {
      num x = 0, y = 0; //成员变量需要重新声明
      void printInfo() => print('($x,$y)'); //成员函数需要重新声明实现
    }
    
    var xxx = Vector(); 
    xxx
      ..x = 1
      ..y = 2
      ..z = 3; //级联运算符,等同于xxx.x=1; xxx.y=2;xxx.z=3;
    xxx.printInfo(); //输出(1,2,3)
    
    var yyy = Coordinate();
    yyy
      ..x = 1
      ..y = 2; //级联运算符,等同于yyy.x=1; yyy.y=2;
    yyy.printInfo(); //输出(1,2)
    print (yyy is Point); //true
    print(yyy is Coordinate); //true
    

    可以看出,子类 Coordinate 采用接口实现的方式,仅仅是获取到了父类 Point 的一个“空壳子”,只能从语义层面当成接口 Point 来用,但并不能复用 Point 的原有实现。

    继承

    使用 extends 关键字来创建一个子类,并可使用 super 关键字引用一个父类,这跟在其他编程语言的使用类似,就不细说了,主要强调下重写操作符。

    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);
    
    // 运算符 == 和 hashCode 的实现未在这里展示,详情请查看下方说明。
    // ···
    }
    
    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 的 Getter 方法。

    noSuchMethod()

    如果调用了对象上不存在的方法或实例变量将会触发 noSuchMethod 方法,你可以重写 noSuchMethod 方法来追踪和记录这一行为:

    class A {
      // 除非你重写 noSuchMethod,否则调用一个不存在的成员会导致 NoSuchMethodError。
      @override
      void noSuchMethod(Invocation invocation) {
      print('你尝试使用一个不存在的成员:' +
      '${invocation.memberName}');
      }
    }
    

    你不能调用一个未实现的方法除非下面其中的一个条件成立:

    • 接收方是静态的 dynamic 类型。
    • 接收方具有静态类型,定义了未实现的方法(抽象亦可),并且接收方的动态类型实现了 noSuchMethod 方法且具体的实现与 Object 中的不同。

    相关文章

      网友评论

        本文标题:Dart - 类(方法、接口、继承)

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