![](/img/trans.png)
[英]Swift Casting Generic to Optional with a nil value causes fatalError
[英]Casting to generic optional in Swift
我在 Swift 中擺弄 generics 並遇到了一些我無法弄清楚的事情:如果我將一個值轉換為通用參數的類型,則不會執行轉換。 如果我對 static 類型進行相同的嘗試,它會起作用。
class SomeClass<T> {
init?() {
if let _ = 4 as? T {
println("should work")
} else {
return nil
}
}
}
if let _ = SomeClass<Int?>() {
println("not called")
}
if let _ = 4 as? Int? {
println("works")
}
誰能解釋這種行為? 兩種情況不應該是等價的嗎?
上面的例子被簡化到最大。 下面的例子說明了更好一點的轉換的必要性
class SomeClass<T> {
init?(v: [String: AnyObject]) {
if let _ = v["k"] as? T? {
print("should work")
} else {
print("does not")
return nil
}
}
}
if let _ = SomeClass<Int?>(v: ["k": 4]) {
print("not called")
}
if let _ = SomeClass<Int>(v: ["k": 4]) {
print("called")
}
在@matt 讓我了解了AnyObject
和Any
之后,@Darko 在他的評論中指出字典如何使我的示例過於復雜,這是我的下一個改進
class SomeClass<T> {
private var value: T!
init?<U>(param: U) {
if let casted = param as? T {
value = casted
} else {
return nil
}
}
}
if let _ = SomeClass<Int?>(param: Int(4)) {
println("not called")
}
if let _ = SomeClass<Int>(param: Int(4)) {
println("called")
}
if let _ = Int(4) as? Int? {
println("works")
}
if let _ = (Int(4) as Any) as? Int? {
println("Cannot downcast from Any to a more optional type 'Int?'")
}
我之前嘗試使用init?(param: Any)
,但這會產生與上一個if
which is discussed elsewhere相同的問題。
所以所有這一切都歸結為:有沒有人真的將任何東西轉換為通用可選類型? 任何狀況之下? 我很樂意接受任何工作示例。
這根本不是關於泛型的; 它是關於AnyObject(以及如何投射)。 考慮:
let d = ["k":1]
let ok = d["k"] is Int?
print (ok) // true
// but:
let d2 = d as [String:AnyObject]
let ok2 = d2["k"] is Int?
print (ok2) // false, though "is Int" succeeds
由於你的初始化程序將字典轉換為[String:AnyObject]
你就在同一條船上。
這現在按預期工作 - 在 Playgrounds 和項目中。 Swift 5.4中復測:
class SomeClass<T> {
private var value: T
init?<U>(param: U) {
if let casted = param as? T {
value = casted
} else {
return nil
}
}
}
if let _ = SomeClass<Int?>(param: Int(4)) {
print("called")
}
if let _ = SomeClass<Int>(param: Int(4)) {
print("called")
}
按預期打印called
。
到目前為止,我可以看到更新代碼的目標是確定傳遞的參數(dict的值)是否為T類型。所以你錯誤地使用as? 施放以檢查類型。 你真正想要的是“是”運營商。
class SomeClass<T> {
init?(v: [String: AnyObject]) {
if v["k"] is T {
print("called if AnyObject is of type T")
} else {
print("called if AnyObject is not of type T")
return nil
}
}
}
if let _ = SomeClass<Int>(v: ["k": 4]) {
print("called")
}
if let _ = SomeClass<Int?>(v: ["k": 4]) {
print("not called")
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.