假设我有一个公开了
mixin
的包,它通过 API 提供了一些可扩展性:
mixin ListenerModifier<T> {
T get value;
void addListener(Callback callback);
void removeListener(Callback callback);
}
假设我想基于这个 mixin 制作一个“插件”:
mixin PreviousValue<T> on ListenerModifier<T> {
late T previous;
const PreviousValue() {
addListener(() => previous = value);
}
}
(您也可以在其他包中定义插件,也许可以公开
Stream<T>
getter。)
然后,用户可以随意使用任何插件,如下所示:
abstract class MyListener<T> with ListenerModifier<T>, PreviousValue<T> {}
问题是,mixins 不能有像上面
PreviousValue
假设的构造函数。是否有一些 OOP/架构方法可以解决这个问题?我最初想到只是强制 PreviousValue
(例如)的用户在其 registerPreviousValue()
构造函数中调用 MyListener
方法作为解决方法,但这很容易出错。
相关:
刚刚意识到我给出的特定示例,我可以使用不同类型的插件系统而无需混合:
mixin ListenerModifierPluginAPI {
T get value;
void addListener(Callback callback);
void removeListener(Callback callback);
}
abstract class ListenerModifier with ListenerModifierPluginAPI {
T registerPlugin<T>(T Function(ListenerModifierPluginAPI) plugin) => plugin(this);
}
class MyListenerModifier extends ListenerModifier {
late final PreviousValueState previousValueState;
const MyListenerModifier() {
previousValueState = registerPlugin(previousValuePlugin);
}
// ...
}
但这可能并不适合所有人。如果有人有不同的解决方案,我会洗耳恭听。
实际上,有一种 OOP 方法可以解决这个问题。 您可以定义必须由使用该 mixin 的任何类实现的抽象 getter。这样你就可以将值放入 mixin 中,甚至强制它发生。 要自动执行 mixin 中的某些 init 函数,您可以给 mixin 一些 bool 标志,该标志显示 mixin 函数是否已经运行,并且您检查 mixin 的内部 getter/setter 和函数。
另一种可能性是定义一个
late final
属性,该属性使用 mixin 的函数,而 mixin 又使用抽象 getter 来初始化其值。由于后期属性初始化器仅在第一次访问时执行,因此可以保证使用 mixin 的实例在此时完全初始化。