I'm trying to pass different classes, with the same properties, to the same function. How do I cast them for use with this function?
Below is a simple example to highlight what I'm trying to achieve.
class A {
var height:Int = 10
}
class B {
var height:Int = 20
}
class C {
static func grow(class:AnyObject) {
class.height + 5
}
}
C.grow(A)
C.grow(B)
The two final calls should yield 15 and 25, but without casting the AnyObject back to A or B, an error like the following is generated: "AnyObject has no member named".
How do I accomplish something like this?
Swift reflection API enables you to read values but not modify them. So if that's enough for you, you may use a method similar to the following which takes an object and the label of the member you want to access:
func getValue<T>(object: AnyObject, memberLabel: String) -> T? {
let mirror = Mirror(reflecting: object)
for member in mirror.children {
if let _ = member.label where member.label == memberLabel,
let value = member.value as? T {
return value
}
}
return nil
}
But if you want to modify the values, you have to define a protocol and make the classes conform to it:
protocol HasHeight {
var height: Int { get set }
}
extension HasHeight {
mutating func grow() {
self.height += 5
}
}
class A : HasHeight {
var height = 10
}
class B : HasHeight {
var height = 20
}
var a = A()
print(a.height)
a.grow()
print(a.height)
var b = B()
print(b.height)
b.grow()
print(b.height)
Here I defined grow()
as a protocol extension so that it is available on every class/struct that conforms to the HasHeight
protocol.
The results are:
10
15
20
25
You may define it elsewhere, but the call will have to be changed to include an &
reference:
func grow<T: HasHeight>(inout sized: T) {
sized.height += 5
}
grow(&b)