Dart中 mixin、extends、implements

Dart中mixin、extends、implements详解

本文同步发表于微信公众号,微信搜索 程语新视界 即可关注,每个工作日都有文章更新

一、对比表格

特性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 个
withextends 之后可选0 或多个
implementswith 之后可选0 或多个

六、选择

什么时候用 extends

  • 当两个类有明显的 IS-A 关系时

  • 需要重用父类的实现代码

  • 需要建立紧密耦合的类层次结构时

什么时候用 implements

  • 当需要实现一个接口契约

  • 当需要多继承接口

  • 当想隐藏实现细节,只暴露接口时

什么时候用 mixin

  • 当需要跨类层次共享代码时

  • 当需要多重继承的功能时

  • 当功能是可选的可组合的

总结:

  1. 继承表示"是什么"(is-a)

  2. 接口表示"能做什么"(can-do)

  3. 混入表示"具有什么特性"(has-a)

  4. 语法强制顺序extends → with → implements

  5. 覆盖控制顺序:想让哪个混入的方法生效,就把它放在更靠后的位置

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值