class 定义一个类,常规的类,定义一些方法、属性。可以被继承
mixin 定义一个类,定义一些方法、属性。 不可以被实例化。可以被混入
abstract class 定义一个抽象类,可以包含抽象方法和具体方法。可以被继承
abstract mixin class 当一个类既需要被继承(作为基类)又需要作为 mixin 提供功能时。 可以被继承和混入
特性 | abstract class |
mixin |
abstract mixin class |
---|---|---|---|
是否可以包含构造函数 | ✅ | ❌ | ❌ |
是否可以包含抽象方法 | ✅ | ✅ | ✅ |
是否可以包含已实现的方法 | ✅ | ✅ | ✅ |
是否可以被实例化 | ❌ | ❌ | ❌ |
是否可以通过 extends 继承 |
✅ | ❌ | ✅ |
是否可以通过 with 混入 |
❌ | ✅ | ✅ |
extends 继承某个常规类,继承父类的属性和方法。
with 继承某个mixin类,加了个新名字,叫混入。主要作用是行为的复用。
on 限制mixin类只能被某些特定的类使用。
implements 用来实现一个或多个类的接口,后面可以是普通类、抽象类或其他接口,实现时需要完全重写这些类的所有方法,无论它们是否已有实现。和继承(对父类)一下,需要使用override明确指出实现某个方法是重写(对接口)。
dart没有多继承,一个类只能extends另外一个类。通过with,可以混入多个mixin类。
1、mixin不能被实例化。
2、mixin不允许存储状态。mixin的如果有属性只能是getter和setter。或者是final属性,在声明的时候就初始化了,不能再修改。这种不允许存储状态的设计,目的也是为了避免对混入类产生副作用。
3、mixin的属性和方法,也不是通过super调用的,直接通过this调用。
4、mixin可以限制哪些类可以混入它,on后面指定类或它的子类才可以使用。
关于mixin不允许存储状态 举例:
mixin RxObjectMixin<T> on NotifyManager<T> {
late T _value; //属性---》提供getter/setter
void refresh() {
subject.add(value);
}
bool firstRebuild = true;//声明时候就初始化了的
bool sentToStream = false; //声明时候就初始化了的
@override
int get hashCode => _value.hashCode;
set value(T val) { //set方法
_value = val;
}
T get value {//get方法
RxInterface.proxy?.addListener(subject);
return _value;
}
Stream<T> get stream => subject.stream; //get方法
}
举例2:
mixin SingleTickerProviderStateMixin<T extends StatefulWidget> on State<T> implements TickerProvider {
Ticker? _ticker;
@override
Ticker createTicker(TickerCallback onTick) {
}
@override
void dispose() {
}
ValueListenable<bool>? _tickerModeNotifier;
@override
void activate() {
}
void _updateTicker() {
}
void _updateTickerModeNotifier() {
}
@override
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
}
}
SingleTickerProviderStateMixin 定义的 _ticker 和 _tickerModeNotifier 是合法的,因为:
- 它们是局部状态,用于实现 mixin 的功能。
- 它们的初始化由方法完成,而不是依赖构造函数。
- 它们的存在不会干扰混入类的其他状态逻辑。
mixin 的设计允许状态存在,但其目标是避免对类的全局状态造成复杂影响,从而提供轻量级的功能复用机制。
“mixin 不存储状态” 的真正含义是什么?
“mixin 不存储状态”的说法主要强调:
- 不直接管理类的核心状态:
mixin 不应强加类的主要状态管理逻辑(例如复杂的初始化、生命周期管理)。
它只应提供功能扩展,而不会对类的全局状态产生较大副作用。
- 避免破坏类的初始化逻辑:
由于 mixin 不能定义构造函数,因此不会与混入类的初始化逻辑冲突。
网友评论