我将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(重点是我):
与Java和C#中的类型系统一样,Dart的类型系统也很完善。它 通过结合使用静态检查来增强这种健全性 (编译时错误)和运行时检查。例如,分配一个 将字符串转换为int是编译时错误。将对象转换为字符串 如果对象不是 字符串。
更新,以回复Rémi的回答:
错误消息是:
The following assertion was thrown building MultiProvider:
type 'List<Word>' is not a subtype of type 'UnmodifiableListView<Word>'
这似乎是协方差与相反的问题。
如果我知道我对List
的引用实际上包含一个UnmodifiableListView
,那么我可以自己进行演员表转换。
为什么编译器会为我添加隐式强制转换?
在我看来,这似乎绕过了上面文档中提到的许多类型健全性。尤其是当我更改类型层次结构并进行广泛的重构时,我依靠编译器告诉我:您混合了类型。 他们的继承树很可能在某个时候仍然是一个共同的祖先。但是它们绝对不一样。
至少对我来说,这甚至更令人惊讶,因为这不是其他“典型” OOP语言(Java,C#等)的工作方式。
所以我仍然想知道:编译器为什么找不到这个,这个设计背后的原因是什么?
答案 0 :(得分:3)
实际上发生的是隐式强制转换。
由于.container {
position: relative;
overflow: hidden;
height: 20px;
width: 100px;
}
.content {
position: absolute;
height: 100%;
width: 100%;
background-color: red;
}
是<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="container">
<div class="content">
a b c d e f g h
</div>
</div>
<a href="#">test</a>
,因此将UnmodifiableListView
分配给List
会自动进行强制转换。
您可以在List
上将其禁用,如下所示:
UnmodifiableListView