我設計了這段代碼來盡可能簡單地說明我的問題。如果我有一個像這樣的通用函式:
func get<T> () -> T? {
//為了舉例說明,我對結果進行了硬編碼。
return 5 as? T ?
}
if let x = get() as? Int { /* Won't compile: 通用引數'T'無法被推斷 */ }
if let x = get() as Int? { /* true */ }
if let x: Int? = get() { /* true */ }
現在我的問題是,為什么第一條不能編譯呢?
我可以使用其他的形式,但這是我想使用的形式,所以我想知道為什么我不能。
uj5u.com熱心網友回復:
這可能是因為 由于這個原因, 另一方面,Swift型別檢查器也是在一個約束系統上作業。
另一方面,如果你使用 我在 Swift 編譯器的源代碼中找到了相關的代碼部分,所以如果你愿意,你可以自己進一步探索它。正如你所看到的,在 在 注意,如果你在 uj5u.com熱心網友回復: Sweeper的回答非常好(像往常一樣);我只想用另一種方式來表達同樣的觀點,也許更簡單。這只是一個告訴和要求之間的區別問題。 編譯器需要被告知T是什么。這就是解決/專門化泛型的意義所在。當你說 但是當你說
標籤:as和as?之間的區別。關鍵的區別在于,如果您使用as,編譯器必須能夠在編譯時告訴您轉換是有效的/將成功的。
get可以回傳的實際型別是有限制的。最終,型別檢查器決定,T是Int。請記住,Swift型別檢查器是在一個約束系統上作業的。as?,LHS運算式可以是任何型別,并且沒有編譯時檢查。在運行時將會檢查轉換,如果它失敗了,運算式就會被評估為nil。因此,as?并不限制其LHS運算式的型別。
visitCoerceExpr(foo as T)中,它這樣做: //加入一個轉換約束,以便在之間直接轉換。
//型別。
CS.addExplicitConversionConstraint(fromType, toType, RememberChoice,
locator)。)
visitConditionalCheckedCastExpr(foo as? T)中,它沒有這樣做。get內的其他地方沒有使用T,你可以直接回傳Any,并讓呼叫者投擲。這將允許你使用as? Int 語法。func get() -> Any{
/ ...
return 5
}
if let x = get() as? Int { /* ... */ }
as Int? 或 :Int? 時,這正是你正在做的。你在告訴編譯器這個東西是一個Int?(所以編譯器可以推理出T是Int)。
as?時,你根本就沒有這樣做。這與Optionals或其他型別沒有任何關系。你只是在詢問(運行時)這是什么型別。你并沒有告訴編譯器(或任何人)任何東西。所以編譯器不知道,你也不能編譯。
