下面是一些(当前)无法编译的代码:
sealed class MyValue<ValueT> {
final ValueT value;
const MyValue(this.value);
const factory MyValue.bool(bool value) = MyBool;
const factory MyValue.num(num value) = MyNumber;
}
final class MyNumber extends MyValue<num> {
const MyNumber(super.value);
}
final class MyBool extends MyValue<bool> {
const MyBool(super.value);
}
Dart 抱怨“重定向构造函数的返回类型‘MyBool/MyNum’不是‘MyValue’的子类型。 尝试重定向到不同的构造函数。”
但是,我不明白为什么。我觉得
const MyValue.bool(true)
成为有效的 MyBool
常数应该是完全可行的。
但这与常量没有任何关系,因为同样的问题也发生在非常量工厂上:
sealed class MyValue<ValueT> {
final ValueT value;
const MyValue(this.value);
factory MyValue.bool(bool value) => MyBool(value);
factory MyValue.num(num value) => MyNumber(value);
}
final class MyNumber extends MyValue<num> {
const MyNumber(super.value);
}
final class MyBool extends MyValue<bool> {
const MyBool(super.value);
}
现在,我确实看到了这个问题,这似乎与我遇到的问题有关,除了在我的情况下,我没有尝试根据输入返回不同的类型。我对答案也不满意,因为类似
sealed class MyValue<ValueT> {
final ValueT value;
const MyValue(this.value);
factory MyValue.bool(bool value) => (MyBool(value) as MyValue<ValueT>);
factory MyValue.num(num value) => (MyNumber(value) as MyValue<ValueT>);
}
final class MyNumber extends MyValue<num> {
const MyNumber(super.value);
}
final class MyBool extends MyValue<bool> {
const MyBool(super.value);
}
不仅可以编译,而且在运行时也完全可以正常工作。问题是,明确的
as
转换似乎是多余的,而且我仍然无法创建 const
实例...
有人可以向我解释为什么类型系统不能按我期望的方式工作吗? (我假设我在这里遗漏了一些东西,并且有一个特定的设计选择导致了我所看到的结果。)还值得一提的是,我真正想做的是制作一种“类型- union”,我可以详尽地
switch
了解“我的价值观”的类型(在本例中,num
和bool
)——所以如果有人可以告诉我另一种方法来实现这一点,那就工作也一样好。预先感谢!
转发构造函数的规则是,它们转发的构造函数必须返回调用构造函数的类型的子类型,对于提供给超类的any类型变量。
如果你写:
class Super<T> {
T get value;
factory Super.bool(bool b) = SubBool;
}
class SubBool implements Super<bool> {
final bool value;
SubBool(this.value);
}
那么你就有问题了,有人可以写:
Super<String>.bool(true);
这是不允许的,因为它的静态类型是
Super<String>
,并且它将创建的值是实现 SubBool
的 Super<bool>
,它不是 Super<String>
。
您只是被禁止编写转发构造函数,而不是试图在某些情况下阻止这种情况,并在其他情况下允许这种情况。
转发构造函数必须创建一个
Super<T>
,并且 SubBool
通常不是 Super<T>
。