我将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类型系统,例如Java和C#中的类型系统。它 使用静态检查的组合来实现这种声音 (编译时错误(和运行时检查。例如,分配 字符串到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#,...(。
所以我仍然想知道:为什么编译器找不到这个设计的原因是什么?
实际上发生了什么是隐式铸件。
因为UnmodifiableListView
是List
,将List
分配给UnmodifiableListView
进行自动铸造。
您可以在analysis_options.yaml
上禁用它:
analyzer:
strong-mode:
implicit-casts: false