【发布时间】:2019-06-26 16:27:04
【问题描述】:
我将 Flutter 应用的数据封装在一个名为 AppData 的类中。有点像这样:
class AppData with ChangeNotifier{
List<word.Word> _words;
UnmodifiableListView<word.Word> words;
AppData(){
// at some point this will be loaded from disk
// for now I'm just using a hardcoded list of words
_words = word.words;
// the following code would work:
// words = UnmodifiableListView(_words);
// this doesn't, but it's also not a compiler error !?
words = _words;
}
// ...
}
AppData 类跟踪单词列表。对于 AppData 的使用者,这可以作为 UnModifiableListView 可见。
我的代码有一个非常明显的错误:我将_words 分配给words,而没有正确地将List 封装在UnModifiableListView 中。
为什么编译器找不到这个?
类型应该是明显的不匹配。来自dart docs(强调我的):
Dart 的类型系统,就像 Java 和 C# 中的类型系统一样,是可靠的。它 使用静态检查的组合来强制执行该健全性 (编译时错误)和运行时检查。例如,分配一个 String to int 是编译时错误。将对象转换为字符串 如果对象不是 字符串。
更新,回应雷米的回答:
错误信息是:
The following assertion was thrown building MultiProvider:
type 'List<Word>' is not a subtype of type 'UnmodifiableListView<Word>'
这似乎是协方差与逆变的问题。
如果我知道我对List 的引用实际上包含UnmodifiableListView,那么我可以自己进行演员表。
为什么编译器会为我添加隐式转换?
在我看来,这似乎绕过了上面文档中提到的许多类型健全性。特别是当我改变我的类型层次结构并进行大量重构时,我依靠编译器告诉我:你把类型弄混了。 他们的继承树很有可能在某个时候仍然到达一个共同的祖先。但它们绝对不一样。
至少对我来说,这更令人惊讶,因为这不是其他“典型”OOP 语言(Java、C#、...)的工作方式。
所以我还是想知道:为什么编译器没有发现这个,这个设计背后的原因是什么?
【问题讨论】: