我需要一个 mixin,我可以在其中访问变量或方法,从它被混合到的类中。
我发现 mixin 和“on”正在完成这项工作。现在我只需要一张心理图景 记住它为什么起作用 - 你能帮忙吗?
首先这个错误让我开始,它是有意义的,因为“on”和“with”都是“心理图片”,正在进入 TestErrorClass,从继承的角度来看,我们只需要一个。
class TestErrorClass with TestErrorMixin {}
mixin TestErrorMixin on TestErrorClass {}
这是我的问题的解决方案,有一个我可以使用的变量,来自 mixin 进入或限制进入的类。
class TestSuper {
String variableWeNeedToAccessFromTestMixin = "";
// It will get TestMixin from "on" in TestMixin, it just doesn't know it yet.
// So we can not use the mixin here - fair enough.
void HelloTestSuper(){}
}
// We need "with" here has it will create the same error as described above if we put it on TestSuper.
// Also we need it to be able to call "HelloTestMixin()" both from here and in instances created from this "TestBase" class.
class TestBase extends TestSuper with TestMixin {
void main(){
HelloTestSuper();
HelloTestMixin();
}
}
// "on" is restricted to only be able to being mixed into classes of this type,
// and there for, we can rely on what ever variables being in the SuperClass and use it here.
// Note variable "variableWeNeedToAccessFromTestMixin".
mixin TestMixin on TestSuper {
void HelloTestMixin(){
print(variableWeNeedToAccessFromTestMixin);
}
}
现在我可以从继承的角度理解“on”和“with”的错误了, mixin 不能两次出现在同一个地方。
但我只能从有限的角度来理解解决方案, 也就是说 mixin 只允许 mixin 到 TestSuper 中。
如果是继承问题,那么从“TestSuper”扩展应该包括“on”到其中的内容。 如果是限制问题,那么首先为什么会出现错误。
希望你能明白我的想法,请提问。
谢谢
以下是 Dart 语言之旅的摘录:
有时您可能想限制可以使用 mixin 的类型。例如,mixin 可能依赖于能够调用 mixin 未定义的方法。如以下示例所示,您可以通过使用 on 关键字指定所需的超类来限制 mixin 的使用:
class Musician {
// ...
}
mixin MusicalPerformer on Musician {
// ...
}
class SingerDancer extends Musician with MusicalPerformer {
// ...
}
在上面的代码中,只有扩展或实现 Musician 类的类才能使用 mixin MusicalPerformer。因为 SingerDancer 扩展了 Musician,所以 SingerDancer 可以在 MusicalPerformer 中混音。
仅基于此,mixins 的
on
更多的是 restriction
机制而不是继承。但是,由于您确切地知道此受限 mixin 将用于特定类(类型),因此您可以使用它的变量和方法。当你思考它时,它与类型转换甚至空安全是一样的 - 如果你确保对象是特定类型,你可以使用它的方法。
此外,这里有一个关于 mixin 如何工作 的精彩解释。
感谢您对 mixins 的回答,我在昨天发布之前已经尝试过,但我认为我管理继承的方式是错误的。
它的工作方式不会破坏全局逻辑:
mixin ConvertibleImplementor on Enum implements Convertible {
@override
double getConversionFactor(Convertible from, Convertible to) {
return from.factor / to.factor;
}
@override
double getConversionFactorFrom(Convertible from) => this.getConversionFactor(from, this);
@override
double getConversionFactorTo(Convertible to) => this.getConversionFactor(this, to);
}
enum TimeUnit with ConvertibleImplementor {
ms(factor: 1/(24*60*60*1000)),
s(factor: 1/(24*60*60)),
min(factor: 1/(24*60)),
h(factor: 1/24),
day(factor: 1),
week(factor: 7),
month(factor: 30.5),
year(factor: 365);
@override
final double factor;
const TimeUnit({required this.factor});
}