将动态类型作为参数传递

时间:2018-03-02 23:54:29

标签: swift generics reflection swift-protocols

我想要实现的是将动态类型的对象作为参数传递给泛型函数。我能够通过type(of:)看到我想要的正确类型,但是我无法将其作为参数传递,因为在泛型函数中我仍然得到静态类型。 以下是我想要做的一个例子:

protocol SomeUsefulProtocol {}

struct MyType1: SomeUsefulProtocol {}
struct MyType2: SomeUsefulProtocol {}

let objects: [SomeUsefulProtocol] = [MyType1(), MyType2()]

let someClosureToWorkWithMyType: Any = { (object: MyType1) in
    //Do some great things
}

func someMethod<T>(type: T.Type, object: Any) {
    typealias ClosureType = (T) -> Void

    if let closure = someClosureToWorkWithMyType as? ClosureType, let object = object as? T {
        closure(object)
    }
}

for object in objects {
    someMethod(type: type(of: object), object: object)
}

这里我希望在对象具有类型“MyType1”时调用闭包someClosureToWorkWithMyType,但在方法内部,对象的类型是静态类型(SomeUsefulProtocol)。

1 个答案:

答案 0 :(得分:0)

这里的问题是object被声明为协议SomeUsefulProtocol的一个实例。协议的实例不是任何特定的具体类型,可以是潜在的许多具体类型之一。

Swift的泛型系统在编译时需要已知的具体类型来创建正确的特化。有许多博客文章和StackOverflow问题和答案深入研究了尝试一起使用Swift协议和Swift泛型的棘手(通常是徒劳的)。

在您的具体示例中,您的方法可以通过以下两种方式之一工作:要么不将object声明为协议实例,而是将其作为具体类型,例如

let object: MyType = MyType()

或者将其声明为原样,但在将其传递给函数时将其强制转换为具体类型,例如

(object as? MyType).flatMap{ someMethod(type: type(of: $0), object: $0) }