為什么向一個通用欄位直接賦值是不可能的,而在使用變數參考或方法回傳值時卻可以做到(這里,相同的值被賦給了變數,而方法回傳相同的值)?
class User {}。
class Teacher extends User{}。
class Student extends User {}。
Future<User> getUser() {
return Future.value(Student())。
}
void main() {
Future<Future<User>> fut = Future.value(getUser()); // <----- No error。
Future<Future<User>> fut2 = Future.value(Future.value(Student())); // <----- 獲得錯誤。
Future<User> userFut3 = Future.value(Student() )。
Future<Future<User>> fut3 = Future.value(userFut3); // <----- No error。
}
當Future.value(Future.value(Student()))直接分配時,獲得以下錯誤。
Error: 引數型別'Student'不能分配給引數型別'FutureOr<Future<User>>?'。
uj5u.com熱心網友回復:
這里的問題是,Future<T>.value的引數具有FutureOr<T>型別。它可以是一個未來或一個值。
此外,Dart型別推理的作業方式是 "向下推 "一個背景關系型別,然后嘗試使運算式在該型別下作業,最后再將最終的靜態型別推回上面。
如果像Future.value(...)這樣的運算式有一個背景關系型別,缺少的型別引數總是從背景關系型別中推斷出來。
當你寫
時 Future<Future<User>> fut2 = Future.value(Future.value(Student()) )。
外部Future.value的背景關系型別,即我們知道它應該具有的型別,是Future<Future<User>>。這使得它的引數具有背景關系型別FutureOr<Future<User>>。
引數是Future.value(Student()),我們對Student()還一無所知,因為我們在型別推理中還沒有涉及到它,我們還在向它努力。
一個Future<X>可以通過兩種方式滿足該FutureOr<Future<User>>,要么是成為一個Future<User>,要么是成為一個Future<Future<User>>;。
型別推理然后猜測它是后者。它是錯的,但它還看不出來。型別推理的作業方式是,當存在背景關系型別時,它必須使用背景關系型別,但背景關系型別是模糊的,它最終選擇了錯誤的選項。
你遇到了型別推理的一個邊緣情況,即背景關系型別可以用兩種不同的方式來滿足,而向下的型別推理選擇了錯誤的一種。這是一個很好的啟發式方法,如果你有一個FutureOr<...>背景關系型別,并且你看到一個Future建構式,你想要的是Future部分的FutureOr<...>/code>。當你有FutureOr<Future<...>>時,它就崩潰了。所以,不要這樣做!
我的建議,完全是為了讓你在未來的日子里能有更多的機會。
我的建議是,在完全通用的情況下,永遠不要在你的程式中出現 uj5u.com熱心網友回復: 因為在函式中你定義了回傳型別,而且dart知道回傳型別,但是當直接賦值時,dart不知道
標籤:Future<Future<anything>>/code>。它不僅可以避免類似的問題,而且對你的代碼來說也是一個更好的模型。
一個最終完成到某個東西的未來,最終完成到一個值......就直接讓它最終完成到那個值。等待中間的 "未來 "只是針鋒相對的忙活。
Future.value(Student())的型別是Future<User>。要解決這個問題,你必須告訴dart值的型別,像這樣。Future.value((Future.value(Student())) as Future<User>);
這樣,dart將知道這個值的型別,并將其視為Future<User>。
