Dart泛型疑问:为何on<Init>()调用触发类型约束错误?
为什么会报错?
你混淆了「泛型参数的约束」和「具体类型的继承关系」。
Bar类的泛型参数E被约束为SomeEvent的子类,这意味着E可以是SomeEvent的任意子类——比如你完全可以定义另一个类class OtherEvent extends SomeEvent{},然后实例化Bar<OtherEvent>。这时候Bar里的E就是OtherEvent,而Init和OtherEvent是平级的兄弟类,没有继承关系,on<Init>()自然不合法。
Dart的静态类型检查会提前阻止这种可能的错误,所以不管你实际会不会实例化Bar<OtherEvent>,只要代码存在这种可能性,检查器就会报错。你看到的E extends SomeEvent提示,只是Bar对E的约束范围,不代表Init一定是E的子类型——E是一个可变的类型参数,不是固定的SomeEvent。
怎么修复?
根据你「让Foo的on方法能接受Foo类型参数的任意子类型」的需求,分两种情况处理:
情况1:Bar的构造函数必须调用on<Init>()
如果Bar内部一定要调用on<Init>(),那必须把Bar的泛型参数E约束为Init的父类(这样Init肯定是E的子类型):
class Bar<E extends Init> extends Foo<E>{ Bar(){ on<Init>(); // 现在合法,因为E是Init的父类,Init extends E } }
但这样Bar只能接受Init或它的父类作为E,范围被缩小了。
情况2:Bar需要支持任意SomeEvent子类作为E,同时on方法能接受E的子类型
这种情况下,不能在Bar的构造函数里硬编码on<Init>(),因为E可能和Init无关。你需要把on方法的调用放到Bar外部,由调用者根据具体的E类型来指定:
class Bar<E extends SomeEvent> extends Foo<E>{ Bar(); } void main() { // 合法:E是SomeEvent,Init是它的子类 Bar<SomeEvent>().on<Init>(); // 合法:E是Init,Init是它自己的子类 Bar<Init>().on<Init>(); // 不合法:E是OtherEvent,Init不是它的子类(符合预期) // Bar<OtherEvent>().on<Init>(); }
另一种思路:让on方法通过参数自动推断类型
如果on方法需要处理具体的事件实例,可以改成通过参数来推断类型,这样代码更直观,也能避免显式指定类型参数的问题:
class Foo<Event>{ // 接受一个Event子类型的实例,自动推断E的类型 void on<E extends Event>(E event) { // 处理event } } class Bar<E extends SomeEvent> extends Foo<E>{ Bar(){ // 如果E是SomeEvent或Init,这里合法;如果E是OtherEvent,会报错(符合预期) on(Init()); } }
内容的提问来源于stack exchange,提问作者John
相关产品推荐
相关产品推荐

