Search code examples
arraysswiftobjectgenericssubclass

Swift return object of type from an array containing class elements


Here is a small code I wrote to explain the problem:

class Vehicle{
    var name:String = ""
    var tyres: Int = 0

}

class Bus:Vehicle{
    var make:String = "Leyland"
}

class Car: Vehicle{
    var model:String = "Polo"
}

let myVehicles:[Vehicle] = [
    Vehicle(),
    Car(),
    Bus()
]

for aVehicle in myVehicles{
    if(aVehicle is Bus){
        print("Bus found")
    }
}

From the code, I can loop through and get the object of type Bus. However, I need a function to do the same thing and return the element of that type if available. I tried using generics but it does not work. I will need something like this:

func getVehicle(type:T.type)->T?{
 // loop through the array, find if the object is of the given type.
 // Return that type object.
}

Solution

  • Use foo as? T to try to cast foo as type T.

    for aVehicle in myVehicles{
        if let bus = aVehicle as? Bus {
            print("Bus found", bus.make)
        }
    }
    

    Your getVehicle can thus be written as:

    func getVehicle<T>() -> T? {
        for aVehicle in myVehicles {
            if let v = aVehicle as? T {
                return v
            }
        }
        return nil
    }
    
    let bus: Bus? = getVehicle()
    

    or functionally:

    func getVehicle<T>() -> T? {
        return myVehicles.lazy.flatMap { $0 as? T }.first
    }
    let bus: Bus? = getVehicle()
    

    (Note that we need to specify the returned variable as Bus? so getVehicle can infer the T.)