簡體   English   中英

在 Swift 中轉換為通用可選

[英]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 讓我了解了AnyObjectAny之后,@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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM