使函数能够处理不同的类作为参数

时间:2016-03-29 21:23:32

标签: swift function casting anyobject

我正在尝试将具有相同属性的不同类传递给同一个函数。如何将它们用于此功能?

下面是一个简单的例子,以突出我想要实现的目标。

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)

两个最终调用应该产生15和25,但是如果不将AnyObject强制转换回A或B,则会生成如下错误:“AnyObject没有名为”的成员。

我如何做到这样的事情?

2 个答案:

答案 0 :(得分:1)

看起来像协议的好例子!使用height属性定义一个,让A和B都实现该协议,然后让grow方法接受协议作为其参数。

答案 1 :(得分:1)

Swift反射API使您可以读取值但不能修改它们。所以如果这对你来说足够了,你可以使用类似下面的方法来获取一个对象和你想要访问的成员的标签:

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
}

但是如果要修改值,则必须定义协议并使类符合它:

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)

在这里,我将grow()定义为协议扩展,以便它在符合HasHeight协议的每个类/结构上都可用。

结果是:

  

10

     

15

     

20

     

25

您可以在其他位置定义它,但必须更改调用以包含&引用:

func grow<T: HasHeight>(inout sized: T) {
    sized.height += 5
}

grow(&b)