Reputation: 2351
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.
}
Upvotes: 3
Views: 2293
Reputation: 1712
You can also use this:
func getVehicle<T>(type: T.Type) -> T? {
return myVehicles.filter { Swift.type(of: $0) == type }.first as? T
}
Usage:
getVehicle(type: Bus.self)
Upvotes: 1
Reputation: 10839
You can also use this:
let a = array.compactMap({ $0 as? MyTypeClass })
// a == [MyTypeClass] no optional
Upvotes: 1
Reputation: 523394
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
.)
Upvotes: 4
Reputation: 15512
You can write it like this :
func getVehicle<T>(type:T)-> [T]{
return myVehicles.filter{ $0 is T }.map{$0 as! T }
}
Upvotes: 3