如何在Swift中调用动态类型的泛型函数

knl*_*knl 6 generics swift

说我有一个协议Fooable:

protocol Fooable {}
Run Code Online (Sandbox Code Playgroud)

现在我需要Fooable使用泛型函数中的类型:

func fooingAround<FooableType: Fooable>(withType: FooableType.Type) {}
Run Code Online (Sandbox Code Playgroud)

当我用一个Fooable类型调用函数时,这工作正常:

struct Foo: Fooable {}
fooingAround(Foo.self) // works fine
Run Code Online (Sandbox Code Playgroud)

但是,我需要Fooable从其他地方检索我交给函数的类型.这是编译器失败的地方:

let fooableType: Fooable.Type = // obtain from somewhere else
fooingAround(fooableType) // compiler error: "Cannot invoke 'fooingAround' with an argument list of type '(Fooable.Type)'"
Run Code Online (Sandbox Code Playgroud)

具体来说,我Fooable.Type从描述API端点的枚举中获取,其中每个端点由不同的Fooable类表示.

我想问题出现是因为我动态获取了一个类型,所以在编译时不能强类型.

有办法解决这个问题吗?

mil*_*los 2

问题是这样的:

let fooableType: Fooable.Type = // obtain from somewhere else
Run Code Online (Sandbox Code Playgroud)

...正在遗忘您想要存储在该变量中的信息,即符合的具体类型是什么Fooable。考虑以下代码可以编译:

protocol Fooable {}

func fooingAround<FooableType: Fooable>(withType: FooableType.Type) {}

struct Foo: Fooable {}
fooingAround(Foo) // works fine

let foo = Foo()
let fooableType /* do not cast here */ = foo.dynamicType

fooingAround(fooableType) // also works fine
Run Code Online (Sandbox Code Playgroud)

...这意味着您必须找到一种方法将类型信息直接通过管道传输到函数调用中而无需进行强制转换。

根据fooingAround您的想法,您可以按照Fooable以下方式进行扩展:

extension Fooable {

    func fooingAround() {
        /* do some fooing with */ self.dynamicType // which is the Foo.Type when called on the `foo` value
    }
}

foo.fooingAround()
Run Code Online (Sandbox Code Playgroud)