Dart泛型类型检查:为何`a is B`不触发类型提升而`a is B<int>`可以?
Dart泛型类型检查的类型推断差异解析
代码示例
class A<T> { const A(this.value); final T value; } class B<T> extends A<T> { const B(super.value); T get getter => value; } void main() { final A<int> a = B<int>(2); if (a is B) { a.getter; // <- Lint: The getter 'getter' isn't defined for the type 'A<int>'. // Work if I do: // (a as B).getter; } if (a is B<int>) { a.getter; } }
问题现象
变量a声明为A<int>类型,实际指向B<int>实例:
- 使用
if (a is B)检查时,分支内的a仍保持A<int>类型,调用getter会触发语法检查错误,必须显式用as转换才能调用; - 使用
if (a is B<int>)检查时,分支内的a会自动被推断为B<int>类型,可直接调用getter。
差异原因
这是Dart类型系统的设计规则导致的:
- 原始类型(raw type)的类型检查不触发类型提升:
if (a is B)中的B是未指定泛型参数的原始类型,编译器无法确认该B的泛型参数是否与A<int>的int匹配,出于类型安全考虑,不会将a的类型提升为B的具体泛型版本,因此分支内a仍保留A<int>类型,自然找不到B类特有的getter方法。 - 明确泛型参数的类型检查会触发类型提升:
if (a is B<int>)明确指定了泛型参数为int,编译器可以确认a的实际类型确实是B<int>,因此会自动将分支内a的类型提升为B<int>,此时就能直接访问B类的成员。
内容的提问来源于stack exchange,提问作者Valentin Vignal
相关产品推荐
相关产品推荐

