跳转到正文
YGJoon 技术博客

Dart 继承和接口详解

发布于:
·1.2k 字 · 约 3 分钟·作者:
Dart 没有 interface 关键字?用隐式接口与多接口实现玩转接口,再讲清抽象类、构造函数继承与多态的实战分寸。
Dart 继承和接口详解文章封面
目录

继承基础

基本语法

class Animal {
  String name;
  
  Animal(this.name);
  
  void makeSound() {
    print('Some sound');
  }
}

class Dog extends Animal {
  Dog(String name) : super(name);
  
  @override
  void makeSound() {
    print('Woof!');
  }
}

构造函数继承

class Person {
  String name;
  int age;
  
  Person(this.name, this.age);
  
  // 命名构造函数
  // 同样,非空字段走初始化列表,不能在构造体里赋值
  Person.guest()
      : name = 'Guest',
        age = 18;
}

class Student extends Person {
  String school;
  
  // 调用父类构造函数
  Student(String name, int age, this.school) : super(name, age);
  
  // 调用父类命名构造函数
  Student.guest(this.school) : super.guest();
}

抽象类

abstract class Shape {
  // 抽象方法
  double getArea();
  double getPerimeter();
  
  // 普通方法
  void printInfo() {
    print('Area: ${getArea()}');
    print('Perimeter: ${getPerimeter()}');
  }
}

class Rectangle extends Shape {
  double width;
  double height;
  
  Rectangle(this.width, this.height);
  
  @override
  double getArea() => width * height;
  
  @override
  double getPerimeter() => 2 * (width + height);
}

接口实现

隐式接口

class Swimmer {
  void swim() {
    print('Swimming');
  }
}

class Duck implements Swimmer {
  @override
  void swim() {
    print('Duck swimming');
  }
}

多接口实现

abstract class Flyer {
  void fly();
}

abstract class Walker {
  void walk();
}

class Bird implements Flyer, Walker {
  @override
  void fly() {
    print('Flying');
  }
  
  @override
  void walk() {
    print('Walking');
  }
}

多态

class Animal {
  String name;

  Animal(this.name);

  void makeSound() {
    print('Some sound');
  }
}

class Cat extends Animal {
  Cat(String name) : super(name);

  @override
  void makeSound() {
    print('Meow!');
  }
}

class Dog extends Animal {
  Dog(String name) : super(name);

  @override
  void makeSound() {
    print('Woof!');
  }
}

void makeAnimalSound(Animal animal) {
  animal.makeSound();
}

void main() {
  Animal cat = Cat('Whiskers');
  Animal dog = Dog('Rover');

  makeAnimalSound(cat); // 输出: Meow!
  makeAnimalSound(dog); // 输出: Woof!
}

完整示例

// 抽象类定义
abstract class Vehicle {
  String brand;
  String model;
  
  Vehicle(this.brand, this.model);
  
  void start();
  void stop();
  
  // 普通方法
  void printInfo() {
    print('$brand $model');
  }
}

// 接口定义
abstract class Electric {
  void charge();
}

abstract class Autonomous {
  void selfDrive();
}

// 基础车辆类
class Car extends Vehicle {
  int seats;
  
  Car(String brand, String model, this.seats) : super(brand, model);
  
  @override
  void start() {
    print('Car engine starting...');
  }
  
  @override
  void stop() {
    print('Car engine stopping...');
  }
}

// 电动车类
class ElectricCar extends Car implements Electric {
  int batteryCapacity;
  
  ElectricCar(
    String brand,
    String model,
    int seats,
    this.batteryCapacity,
  ) : super(brand, model, seats);
  
  @override
  void charge() {
    print('Charging electric car...');
  }
  
  @override
  void start() {
    print('Electric car starting silently...');
  }
}

// 自动驾驶电动车
class AutonomousElectricCar extends ElectricCar implements Autonomous {
  AutonomousElectricCar(
    String brand,
    String model,
    int seats,
    int batteryCapacity,
  ) : super(brand, model, seats, batteryCapacity);
  
  @override
  void selfDrive() {
    print('Self-driving mode activated');
  }
}

void main() {
  // 创建不同类型的车辆
  Car regularCar = Car('Toyota', 'Camry', 5);
  ElectricCar tesla = ElectricCar('Tesla', 'Model 3', 5, 75);
  AutonomousElectricCar waymo = AutonomousElectricCar('Waymo', 'One', 4, 100);
  
  // 使用多态
  List<Vehicle> vehicles = [regularCar, tesla, waymo];
  
  for (var vehicle in vehicles) {
    vehicle.printInfo();
    vehicle.start();
    vehicle.stop();
    
    if (vehicle is Electric) {
      (vehicle as Electric).charge();
    }
    
    if (vehicle is Autonomous) {
      (vehicle as Autonomous).selfDrive();
    }
    
    print('---');
  }
}

注意事项

  1. Dart 不支持多重继承
  2. 一个类可以实现多个接口
  3. 接口可以包含实现
  4. 注意方法重写的正确性
  5. 合理使用抽象类和接口

最佳实践

  1. 优先使用接口而不是继承
  2. 抽象类用于定义通用行为
  3. 合理使用多态
  4. 避免过深的继承层次
  5. 遵循里氏替换原则

实战观点:我的项目里几乎不用继承

说出来可能有点反直觉:我这几个 Flutter 项目(flutter_brightness、某物流冷链项目、ygking_json_to_dart_model)里,几乎看不到 extends。SerialService、JsonConverter、LuxData——全是独立的类,谁也不继承谁。

不是我不会用,而是被坑过之后的选择。继承的问题在于隐式耦合:子类自动获得父类的一切,包括你不想要的。Flutter 官方自己都在淡化继承——Widget 体系里,组合(child:/children:)才是主流,继承只用在极少数基础类上。

那什么时候用 implements(接口)?我的标准是:当你需要”多种实现可以互换”时。比如 flutter_brightness 里,如果以后要支持”除了串口,还能从网络读光照数据”,我会定义一个 abstract class LightSensorReader,然后 SerialLightSensorReader implements LightSensorReader、NetworkLightSensorReader implements LightSensorReader。接口的价值在”第二个实现”出现时才兑现——只有一个实现时,写接口就是过度设计。

Dart 里还有个细节:所有的类都隐式定义了接口(class A 可以直接被 implements,不需要 abstract)。这个设计让”先写实现、后抽接口”很顺滑——SerialService 现在是具体类,哪天需要多实现,直接 implements SerialService 就行,不用改原代码。

参考:Dart 官方文档(dart.dev)“Classes” 章节

总结

Dart 里 extends 是”是一种”,implements 是”能干什么”——大部分时候后者更够用。继承层级超过两层就该停下来想想是不是该用组合;接口等到第二个实现冒头再抽,提前写只是自我感动。


分享这篇文章:


相关文章

上一篇
Dart 反射和镜像详解
下一篇
Dart 语言中常见的设计模式