使用“ is”检查Dart泛型的运行时类型

时间:2018-10-06 01:06:21

标签: generics dart

我对Dart还是比较陌生,并且正在尝试对代数数据类型进行建模(例如带有关联值的Swift枚举)。

但是,当我尝试检查值的运行时类型时,我看到了一些我不太了解的行为。考虑以下代码:

abstract class Fetchable<T> {
  factory Fetchable.success(T object) = FetchableSuccess;
  factory Fetchable.error(Error error) = FetchableError;
}
class FetchableSuccess<T> implements Fetchable<T> {
  final T object;
  const FetchableSuccess(this.object);
}
class FetchableError<T> implements Fetchable<T> {
  final Error error;
  const FetchableError(this.error);
}

void main() {
  // ------------- CASE 1 -------------
  final s = Fetchable.success("hi there");
  print(s.runtimeType);                             // FetchableSuccess<dynamic>
  print(s is FetchableSuccess);                     // true
  print(s is FetchableSuccess<String>);             // false
  print(s is FetchableSuccess<dynamic>);            // true

  if (s is FetchableSuccess) {
    print(s.object);                                // compile error 
  }
  if (s is FetchableSuccess<dynamic>) {
    print(s.object);                                // compile error
  }

  // ------------- CASE 2 -------------
  final e = Fetchable.error(StateError("uh oh"));
  print(e is FetchableError);                       // true
  if (e is FetchableError) {
    print(e.error);                                 // Works OK
  }
}

如您所见,我创建了两个案例...我似乎似乎无法从object案例中提取success变量。 is关键字告诉我它是一个FetchableSuccess<dynamic>(这似乎很奇怪……我以为Dart不会删除该类型?我希望它是一个FetchableSuccess<String>

尽管如此,即使我强制转换为FetchableSuccess<dynamic>,编译器仍然告诉我它不知道object子类中的FetchableSuccess变量。

不过,与FetchableError(未明确使用类型为T的值)进行对比... is正常工作,编译器可以访问{ {1}}变量。

我想念什么?任何指导将不胜感激。

2 个答案:

答案 0 :(得分:3)

我们这里有两个问题:首先,您需要在两个工厂构造函数的右侧添加<T>

如果这样做,s的运行时类型应为ReflectableSucces<String>,那么您将从{{1}的以下三行中获得true }。

然后您正在测试main,这意味着s is FetchableSuccess,并且它不是静态已知类型s is FetchableSuccess<dynamic>的子类型,因此您不会获得晋升(因此没有{{ 1}}静态类型的getter,因此出现错误)。明确测试Fetchable<String>当然也要接受同样的处理。

所以剩下的问题是,为什么您没有为那些缺少object的人弄错?我正在为此寻找问题,这可能是一个已知的错误。

更新:https://github.com/dart-lang/sdk/issues/34714解决了这样一个事实,即即使应该在公共前端也不进行推断。因此,我们使用分析器的推论来进行分析,然后在运行时获得不使用推论的语义(因此默认为s is FetchableSucces<dynamic>),这就是我们在实际情况下遇到这种不幸冲突的原因。 type参数在运行时错误,并且没有编译时错误。当该问题着陆时,应解决该问题。

答案 1 :(得分:1)

我同意,这真的很奇怪。简短的解释:类型被推断为class FileSaver { static void Main() { // Create a StreamWriter instance StreamWriter writer = new StreamWriter(Application.PersistentDataPath + "/droidlog.txt"); // This using statement will ensure the writer will be closed when no longer used using(writer) { // Loop through the numbers from 1 to 20 and write them for (int i = 1; i <= 20; i++) { writer.WriteLine(i); } } } } ,因此,这里有三种有趣的解决方法:

Fetable<String>

我将向语言人员发送电子邮件,看看他们是否有想法。