Casting to generic optional in Swift

偶尔善良 提交于 2019-12-10 04:33:54

问题


I'm fiddling around with generics in Swift and hit something I can't figure out: If I cast a value into the type of a generic parameter, the cast is not performed. If I try the same with static types, it works.

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")
}

Can anybody explain this behavior? Shouldn't be both cases equivalent?

Update

The above example is simplified to the max. The following example illustrates the need for a cast a little better

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")
}

2nd Update

After @matt made me learn about AnyObject and Any and @Darko pointed out in his comments how dictionaries make my example too complicated, here's my next refinement

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?'")
}

I tried using init?(param: Any) before, but that yields the same problem illustrated in the last if which is discussed elsewhere.

So all it comes down to: Has anyone really been far as to ever cast anything to a generic optional type? In any case? I'm happy to accept any working example.


回答1:


This is really not about generics at all; it's about AnyObject (and how casting works). Consider:

    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

Since your initializer casts the dictionary up to [String:AnyObject] you are in this same boat.




回答2:


As far I can see the goal of your updated code is to find out if the passed parameter (the value of the dict) is of type T. So you are mis-using the as? cast to check the type. What you actually want is the "is" operator.

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")
}


来源:https://stackoverflow.com/questions/32080420/casting-to-generic-optional-in-swift

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!