Say I have a protocol Fooable
:
说我有一个协议Fooable:
protocol Fooable {}
Now I need to work with a Fooable
type in a generic function:
现在我需要在泛型函数中使用Fooable类型:
func fooingAround<FooableType: Fooable>(withType: FooableType.Type) {}
This works fine when I just call the function with a Fooable
type:
当我只用Fooable类型调用函数时,这很好用:
struct Foo: Fooable {}
fooingAround(Foo.self) // works fine
However, I need to retrieve the Fooable
type that I hand over to the function from somewhere else. This is where the compiler fails:
但是,我需要检索我从其他地方移交给函数的Fooable类型。这是编译器失败的地方:
let fooableType: Fooable.Type = // obtain from somewhere else
fooingAround(fooableType) // compiler error: "Cannot invoke 'fooingAround' with an argument list of type '(Fooable.Type)'"
Specifically, I obtain the Fooable.Type
from an enum that describes API endpoints, where each endpoint is represented by a different Fooable
class.
具体来说,我从描述API端点的枚举中获取Fooable.Type,其中每个端点由不同的Fooable类表示。
I suppose the problem arises because I dynamically obtain a type, so there can be no strong typing at compile time.
我想问题出现是因为我动态获取了一个类型,所以在编译时不能强类型化。
Is there a way to work around this?
有办法解决这个问题吗?
1 个解决方案
#1
1
The problem is that this:
问题是这个:
let fooableType: Fooable.Type = // obtain from somewhere else
... is casting into oblivion precisely the information you want to store in that variable, i.e. what is the concrete type that is conforming to Fooable
. Consider that the following code compiles:
...正在遗忘您想要存储在该变量中的信息,即符合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
... which means that you have to find a way to directly pipe the type information into your function call without casting.
...这意味着您必须找到一种方法直接将类型信息传递到函数调用中而不进行强制转换。
Depending on the sort of fooingAround
you have in mind, you may for example be able to extend Fooable
along the following lines:
根据您所考虑的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()
#1
1
The problem is that this:
问题是这个:
let fooableType: Fooable.Type = // obtain from somewhere else
... is casting into oblivion precisely the information you want to store in that variable, i.e. what is the concrete type that is conforming to Fooable
. Consider that the following code compiles:
...正在遗忘您想要存储在该变量中的信息,即符合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
... which means that you have to find a way to directly pipe the type information into your function call without casting.
...这意味着您必须找到一种方法直接将类型信息传递到函数调用中而不进行强制转换。
Depending on the sort of fooingAround
you have in mind, you may for example be able to extend Fooable
along the following lines:
根据您所考虑的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()