简体   繁体   中英

Swift generic type cast

I have a generic class where I have an array of generic types. No I want to do some operations based on the class in the array. I have 2 classes: Person and House (no Inheritance). But this code doesn't work:

let allValues = [T]()
if allValues[0] is Person { 
     let values = (allValues as [Person])
}

But this doesn't work as T is not identical to 'Person' . What do I have to do? Thanks for any help.

You can't do this (or at least, not without jumping through some pretty tortuous and inadvisable hoops). You are thinking of T more like the Any type, which is a type that can hold any other type and that you can turn back into the real type with as (or probably preferably as? ) at runtime.

But generics don't work like this. Within your code, the generic T will be replaced with a real type at compile time, and that type might not be a Person . What would the code above do if that were the case?

What is the underlying functionality you're actually trying to achieve? People and houses are very different so do you really need to write a function that operates generically on both of them?

I agree with Oliver Borchert and Airspeed Velocity : this kind of problem should be addressed using a protocol.

However you can perform the cast you asked about using this syntax:

let values = allValues as Any as [Person]

Now I see 2 problems:

  1. Your IF will crash because your array allValues contains 0 elements and you are accessing the first one (that does not exist).
  2. allValues could have a Person at the first element and something else at the second position. This makes dangerous a cast after having evaluated only the first element.

    Example

    class LifeForm {}

    class Person : LifeForm {}

    With T equals to LifeForm.

I think the following version is safer because you are directly evaluating the type T.

class Things<T>{
    func doSomething() {
        let allValues = [T]()
        // populate allValues....
        if T.self is Person.Type {
            println("List of Person")
            let values = allValues as Any as [Person]
        }
    }
}

Important: I provided this code just to show the syntax. I don't like this abborach (again, a Protocol would be better) because the class Things contains logic specific to Person. Ideally Things should know nothing about Person because Things is a generic class.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM