![](/img/trans.png)
[英]Dart value becomes dynamic during runtime. Causing TypeError: type is not a subtype of dynamic (type comes from generics)
[英]Dart Generics - type is not a subtype
我從 Dart 通用 function 收到運行時錯誤:
Widget card = widget.cardBuilder(item);
其中產生:
type '(Contact) => Widget' is not a subtype of type '(DeletableItem) => Widget'
聯系人 class 定義為
class Contact
implements DeletableItem
{
然后我有一個方法:
class UndoableListView<T extends DeletableItem>
{
List<T> children;
final Widget Function(T item) cardBuilder;
這就是發生運行時錯誤的地方
Widget buildItem(BuildContext context, int index) {
T item = children[index];
Widget card = widget.cardBuilder(item); <<<<< error thrown here.
我顯然誤解了 generics 的工作原理。
Contact 顯然擴展了 DeleteableItem。
那我做錯了什么?
Contact
擴展了DeletableItem
,並且是它的子類型。
函數的參數是逆變的,所以
Widget Function(Contact)
不是的子類型
Widget Function(DeletableItem)
事實上,情況恰恰相反。
函數以這種方式運行,因為子類型化意味着可替換性。 您可以在任何需要DeletableItem
的地方使用Contact
(因為它實現了整個DeletableItem
接口),因此Contact
是DeletableItem
的子類型。
您可以在任何需要Widget Function(Contact)
Widget Function(DeletableItem)
地方使用 Widget Function(DeletableItem),因為您可以使用任何Contact
調用 function(它會按預期返回Widget
)。 所以Widget Function(DeletableItem)
是Widget Function(Contact)
的子類型。
Dart generics 是協變的,盡管它並不總是正確的。
這意味着UndoableListView<Contact>
是UndoableListView<DeletableItem>
的子類型。
問題的出現是因為cardBuilder
字段在function類型中逆變使用了class類型參數,
final Widget Function(T item) cardBuilder;
所以,當你這樣做時:
UndoableListView<DeletableItem> list = UndoableListView<Contact>();
var builder = list.cardBuilder;
你得到一個錯誤。 list.cardBuilder
表達式有一個static 類型的Widget Function(DeletableItem)
,但是一個運行時類型的Widget Function(Contact)
,它不是 static 類型的子類型。 這是一個類型健全性問題,編譯器知道這一點,它會插入一個類型檢查以確保builder
變量不會以無效類型的值結束。
那張支票拋出。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.