本文同步发表于微信公众号,微信搜索 程语新视界 即可关注,每个工作日都有文章更新
一、对比表格
| 特性 | extends (继承) | implements (实现) | mixin (混入) |
|---|---|---|---|
| 目的 | 类继承,获取父类功能 | 实现接口契约 | 代码复用,多继承 |
| 数量限制 | 单继承 | 多实现 | 多混入 |
| 访问权限 | 可访问父类非私有成员 | 只能访问接口定义 | 可访问混入的非私有成员 |
| 构造函数 | 可调用父类构造函数 | 无构造函数 | 无构造函数 |
| super调用 | 可调用父类方法 | 不能调用 | 可调用 super(线性化顺序) |
| 抽象方法 | 可选择实现 | 必须全部实现 | 可选择实现 |
| Dart版本 | 所有版本 | 所有版本 | Dart 2.1+ |
二、extends (继承)
2.1 语法和特性
// 父类
class Animal {
String name;
int age;
Animal(this.name, this.age);
void eat() {
print('$name is eating');
}
void sleep() {
print('$name is sleeping');
}
void _privateMethod() { // 私有方法,只能在当前文件访问
print('Private method');
}
}
// 子类继承
class Dog extends Animal {
String breed;
// 调用父类构造函数
Dog(String name, int age, this.breed) : super(name, age);
// 重写父类方法
@override
void eat() {
print('$name the $breed is eating dog food');
}
// 新增方法
void bark() {
print('$name is barking');
}
// 调用父类方法
void sleepAndEat() {
super.sleep(); // 调用父类 sleep()
eat(); // 调用当前类 eat()(可能是重写后的)
}
}
// 使用
void main() {
Dog dog = Dog('Buddy', 3, 'Golden Retriever');
dog.eat(); // Buddy the Golden Retriever is eating dog food
dog.sleep(); // Buddy is sleeping (继承自Animal)
dog.bark(); // Buddy is barking
dog.sleepAndEat(); // 先调用父类sleep,再调用当前eat
}
2.2 继承的限制
// Dart 是单继承语言
class A {}
class B {}
// class C extends A, B {} // 错误:不能多继承
// 但可以通过多层继承实现类似效果
class A {}
class B extends A {}
class C extends B {} // C 间接继承了 A 和 B 的特性
三、implements (实现接口)
3.1 语法
// 定义一个接口(在Dart中,所有类都隐式定义了一个接口)
abstract class Vehicle {
void start();
void stop();
int get maxSpeed;
}
// 另一个接口
abstract class Electric {
void charge();
int get batteryLevel;
}
// 实现多个接口
class TeslaCar implements Vehicle, Electric {
int _speed = 0;
int _battery = 100;
@override
void start() {
print('Tesla starting silently');
_speed = 10;
}
@override
void stop() {
print('Tesla stopping with regenerative braking');
_speed = 0;
}
@override
int get maxSpeed => 250;
@override
void charge() {
print('Charging Tesla');
_battery = 100;
}
@override
int get batteryLevel => _battery;
// 可以添加额外的方法
void autopilot() {
print('Autopilot engaged');
}
}
3.2 与继承的区别
class BaseClass {
String name = 'Base';
void method() {
print('Base method');
}
void inheritedMethod() {
print('This will NOT be available in implementer');
}
}
// extends:获得实现
class ChildExtends extends BaseClass {
@override
void method() {
print('Child method');
super.method(); // 可以调用父类方法
}
void test() {
print(name); // 可以访问字段
inheritedMethod(); // 可以访问父类方法
}
}
// implements:只获得接口
class ChildImplements implements BaseClass {
// 必须重新实现所有公共成员
@override
String name = 'Child'; // 必须重新声明
@override
void method() {
print('Child method');
// super.method(); //错误:没有super可用
}
// 缺少 inheritedMethod 的实现
// 必须添加:
@override
void inheritedMethod() {
print('Reimplemented');
}
}
四、mixin (混入)
4.1 用法
// 定义 mixin
mixin Swimming {
void swim() {
print('Swimming in water');
}
// mixin 可以有具体实现
void breatheUnderwater() {
print('Holding breath');
}
}
mixin Flying {
void fly() {
print('Flying in the air');
}
double get maxAltitude; // 抽象成员
}
// 使用 mixin
class Duck with Swimming, Flying {
@override
double get maxAltitude => 100.0; // 实现抽象成员
void quack() {
print('Quack quack');
}
}
// 使用
void main() {
Duck duck = Duck();
duck.swim(); // Swimming in water
duck.fly(); // Flying in the air
duck.quack(); // Quack quack
print(duck.maxAltitude); // 100.0
}
4.2 mixin 的限制和约束
// mixin 不能有构造函数
// mixin Animal { //错误
// Animal(); // mixin 不能有构造函数
// }
// 使用 on 关键字限制 mixin 的使用范围
mixin Musical on Animal { // 只能用于 Animal 或其子类
void playMusic() {
print('Playing music');
}
}
class Animal {
void breathe() {
print('Breathing');
}
}
class Bird extends Animal with Musical {
// 正确:Bird 继承自 Animal
}
class Chair {
// class Chair with Musical {} //错误:Chair 不是 Animal
}
五、三者组合使用
5.1 顺序规则
class 类名 extends 父类 with 混入类1, 混入类2, ... implements 接口1, 接口2, ... {
// 类体
}
5.2 语法示例
class SuperClass {
void superMethod() => print('Super method');
}
mixin MixinA {
void mixinMethod() => print('Mixin A method');
}
mixin MixinB {
void mixinMethod() => print('Mixin B method');
}
abstract class InterfaceA {
void interfaceMethod();
}
//正确:标准顺序
class GoodClass extends SuperClass
with MixinA, MixinB
implements InterfaceA {
@override
void interfaceMethod() {
print('Interface method implementation');
}
}
//错误:顺序混乱会导致编译错误
// class BadClass1 implements InterfaceA extends SuperClass {} // Error
// class BadClass2 with MixinA extends SuperClass {} // Error
// class BadClass3 extends SuperClass implements InterfaceA with MixinA {} // Error
void main() {
GoodClass obj = GoodClass();
obj.superMethod(); // 继承的方法
obj.mixinMethod(); // MixinB 的方法(最后一个 mixin 胜出)
obj.interfaceMethod(); // 实现的接口方法
}
5.3 语法顺序规则
| 关键字 | 位置 | 是否必须 | 数量限制 |
|---|---|---|---|
| extends | 第一个 | 可选(默认 Object) | 0 或 1 个 |
| with | extends 之后 | 可选 | 0 或多个 |
| implements | with 之后 | 可选 | 0 或多个 |
六、选择
什么时候用 extends?
-
当两个类有明显的 IS-A 关系时
-
需要重用父类的实现代码时
-
需要建立紧密耦合的类层次结构时
什么时候用 implements?
-
当需要实现一个接口契约时
-
当需要多继承接口时
-
当想隐藏实现细节,只暴露接口时
什么时候用 mixin?
-
当需要跨类层次共享代码时
-
当需要多重继承的功能时
-
当功能是可选的或可组合的时
总结:
-
继承表示"是什么"(is-a)
-
接口表示"能做什么"(can-do)
-
混入表示"具有什么特性"(has-a)
-
语法强制顺序:
extends→with→implements -
覆盖控制顺序:想让哪个混入的方法生效,就把它放在更靠后的位置
Dart中mixin、extends、implements详解
1460

被折叠的 条评论
为什么被折叠?



