Dart中的抽象类abstract、extends、implements

2,208 阅读3分钟

抽象类(Abstract classes)

本篇文章, 我们一起学习、温顾下Dart基础语法中的抽象类, 还有抽象方法。以及怎样使用抽象类?

根据官方文档解释, 我们可以知道:

  • Dart 没有 interface 关键字。相反,所有的类都隐式定义了一个接口。因此,任意类都可以作为接口被实现。也就是说, Dart中的接口也是abstract关键字定义的。
  • 使用关键字 abstract 标识类可以让该类成为 抽象类,抽象类将无法被实例化。
  • 如果想让抽象类同时可被实例化,可以为其定义 工厂构造函数
  • 抽象类常用于声明接口方法、有时也会有具体的方法实现。抽象类中声明的抽象方法, 子类必须实现。抽象类中的实现方法, 子类不必须实现。

以一个Animal类来说明。

抽象类使用extends关键字

/// 抽象类Animal
abstract class Animal {
  speak(); /// 抽象方法, 子类必须实现该方法
  
  printInfo() {  /// 不是抽象方法, 子类不需要实现
    print('---- Animal, not abstract method');
    /// 调用了speak方法
    speak();
  }
}

/// 子类Dog
class Dog extends Animal {
  /// 必须实现抽象类的抽象方法
  @override
  speak() {
    print('---- Dog, 实现了抽象方法speak');
  }
}

/// 子类Cat
class Cat extends Animal {
  @override
  speak() {
    print('-----Cat, 实现了抽象方法speak');
  }
}

void main() {  
  Dog d1 = Dog();
  d1.speak();
  d1.printInfo(); /// 方法内部调用了speak()方法
  
  Cat c1 = new Cat();
  c1.speak();
  c1.printInfo();
}

输出结果: 

---- Dog, 实现了抽象方法speak
---- Animal, not abstract method
---- Dog, 实现了抽象方法speak

-----Cat, 实现了抽象方法speak
---- Animal, not abstract method
-----Cat, 实现了抽象方法speak

抽象类使用extends关键字。

抽象类使用implements关键字

抽象类不能实例化。接口也是 abstract 关键字声明的,并且需要使用 implements 关键字来实现。

下面模拟一个数据库接口, 并且实现一个Mysql的类:

/// abstract关键字声明接口
abstract class DB {
  String? host;
  String? port;
  String? user;
  String? pass;
  query(String? data); /// 抽象方法
  update(String? data); /// 抽象方法
  insert(String? data); /// 抽象方法
  delete(String? data); /// 抽象方法
}

/// implements 实现接口
class Mysql implements DB {
  @override
  String? host;

  @override
  String? pass;

  @override
  String? port;

  @override
  String? user;

  Mysql(this.host, this.user, this.pass, [this.port = '3306']) {
    print(
        '[ok] connect to ${this.host}:${this.port}, use ${this.user}:${this.pass}');
  }

  @override
  delete(String? data) {
    print('delete ${data}');
  }

  @override
  insert(String? data) {
    print('insert ${data}');
  }

  @override
  query(String? data) {
    print('query ${data}');
  }

  @override
  update(String? data) {
    print('update ${data}');
  }
}

void main() {
    /// 初始化、并调用 
  Mysql my = Mysql('127.0.0.1', 'root', '123456', '3307');
  my.insert('121');
  my.update('121');
  my.query('121');
  my.delete('121');
}

输出结果:
[ok] connect to 127.0.0.1:3307, use root:123456
insert 121
update 121
query 121
delete 121

抽象类使用implements关键字, 多接口

abstract class A {
  fnA();
}

abstract class B {
  fnB();
}

class C implements A, B {
  @override
  fnA() {
    print('FN------A');
  }

  @override
  fnB() {
    print('FN------B');
  }
}

void main() {
  C c = new C();
  c.fnA();
  c.fnB();
}

输出接果:
FN------A
FN------B

extends扩展、继承关键字

Dart 支持单继承。

使用 extends 关键字来创建一个子类,并可使用 super 关键字引用一个父类:

class Television {
  void turnOn() {
    _illuminateDisplay();
    _activateIrSensor();
  }
  // ···
}

class SmartTelevision extends Television {
  void turnOn() {
    super.turnOn();
    _bootNetworkInterface();
    _initializeMemory();
    _upgradeApps();
  }
  // ···
}

extends、implements关键字的区别

  • extends: 继承abstract后, 子类必须实现父类的抽象方法。不必实现父类里面已经实现的方法。
  • implements: 继承abstract后, 子类必须实现父类的所有方法。不管是父类里面已经实现的方法、还是未实现的方法。

参考资料

abstract抽象类

extends扩展一个类

Dart 抽象类 abstract 、抽象类实现接口、混入 mixin

工厂构造函数