任何人都可以向我解釋爲什麼這個例子中的最後一種情況是編譯錯誤?通用函數和子類。任何人都可以解釋此編譯錯誤?
class A{}
class B: A{}
protocol Finder{
func find< T: A>(_ f: (T)->Bool) -> T?
}
class FinderImpl : Finder{
func find<T : A>(_ f: (T) -> Bool) -> T? {
//In the real code I use T to find the instance. I.e. CoreData
return nil
}
}
let finder = FinderImpl()
//OK
let optionalB : B? = finder.find{_ in true}
let a : A = finder.find{_ in true}!
let b : B = finder.find{(b: B) in true}!
//Compile Error
let b2 : B = finder.find{_ in true}!
let a。編譯器使用(A) -> Bool.
作爲閉包類型。然後返回類型爲A.
讓b。這是因爲關閉具有明確的信息編譯:(B)->Bool
let optionalB。我不知道爲什麼這個案件有效,在這裏封閉也沒有任何信息。區別在於! operator
錯誤:在最後一種情況下,編譯器無法推斷傳遞給func find的閉包的類型。它建議我投as! B
,因爲它認爲封閉類型是(A)->Bool
。它不使用
重要參考B2型B的:我不能投as! B
,因爲我需要查找功能實際使用的B型。如果我投as! B
,該函數將使用A型和獲得錯誤的例子。代碼會編譯,但結果是錯誤的。
如果我刪除了T:A
限制,則不存在編譯錯誤。
這看起來像是一個編譯器bug。我認爲編譯器應該使用b2的類型來知道閉包是(B)->Bool
,然後是find的結果類型。 T:A
限制和閉包中缺少類型信息會導致失敗。
我失去了一些東西在這裏?有什麼想法嗎?
嗨,謝謝你的回答。我理解你的觀點,我想我也是在這個問題中提到的。我看到的問題是,在讓b2:B,我實際上指定了類型信息。 T = B。我不明白爲什麼有必要明確說明(B) - > Bool。以可選B爲例,那裏我沒有指定閉包類型,但它的工作原理。這就是爲什麼我認爲這可能是一個編譯器錯誤。有什麼想法嗎? – Lio