我正在研究一些通用串列實用程式函式,當主要變數是串列時,通用函式的型別推斷似乎存在問題。這通過以下代碼進行了演示:
List<T> combine<T>(List<T> a, List<T> b, T Function(T a, T b) combiner) {
final list = <T>[];
for (int i = 0; i < a.length && i < b.length; i ) {
list.add(combiner(a[i], b[i]));
}
return list;
}
void main() {
final a = [5, 8];
final b = [7, -3];
final c = combine(a, b, (a, b) => a b); // Error
print(c);
// Expected: [12, 5]
}
當我按原樣使用此代碼時,lambda 中的型別推斷會設定a和bto be Object?,這會導致以下錯誤訊息:
不能無條件呼叫運算子“ ”,因為接收者可以為“null”。嘗試向目標添加空檢查('!')。
執行錯誤訊息中的操作會將訊息更改為以下內容:
沒有為“物件”型別定義運算子“ ”。嘗試定義運算子“ ”。
問題顯然是型別推斷將引數分配給Object?而不是預期的int. 這可以通過鍵入引數或將泛型型別顯式傳遞給函式來解決:
final c = combine(a, b, (int a, int b) => a b);
// OR
final c = combine<int>(a, b, (a, b) => a b);
然而,這是一個額外的冗長級別,我不想強??迫這些實用功能的用戶必須這樣做(更不用說當我必須向他們解釋時這將是一個支持問題)。有沒有辦法更改函式簽名以使其型別推斷按預期作業?
uj5u.com熱心網友回復:
這基本上是Dart List.fold 與 List.reduce 型別推斷,但在您的情況下,您可以通過使您的函式成為擴展方法來回避問題,以便T從接收器而不是從引數中推斷:
extension<T> on List<T> {
List<T> combineWith(List<T> b, T Function(T a, T b) combiner) {
final list = <T>[];
for (int i = 0; i < length && i < b.length; i ) {
list.add(combiner(this[i], b[i]));
}
return list;
}
}
void main() {
final a = [5, 8];
final b = [7, -3];
final c = a.combineWith(b, (a, b) => a b); // Error
print(c);
// Expected: [12, 5]
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/460197.html
上一篇:Java:泛型型別引數之間的區別
