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

Make a Functions Able to Handle Different Classes as Parameters

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

下面是一个简单的例子来突出我正在努力实现的目标。

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 has no member named".

我该如何完成这样的事情?

看起来是一个很好的协议案例!定义一个高度 属性,让 A 和 B 都实现该协议,然后让 grow 方法接受该协议作为其参数。

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协议的class/struct上使用。

结果是:

10

15

20

25

您可以在别处定义它,但必须更改调用以包含 & 引用:

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

grow(&b)