swift 函数中的嵌套泛型
Nested generics in a swift function
假设我有这段代码:
protocol MyProtocol {
}
struct MyStruct: MyProtocol {
}
class MyClass<P: MyProtocol> {
// Required for compiling
required init() {
}
}
class MySpecialClass: MyClass<MyStruct> {
}
func foo<P: MyProtocol, C: MyClass<P>>(protocolType: P.Type) -> C {
return C()
}
这样编译调用
let specialClass: MySpecialClass = foo(protocolType: MyStruct.self)
创建类型 MySpecialClass
的实例。
我想要的是不必传入 P
的类型,这样我就可以简单地调用
let specialClass: MySpecialClass = foo()
自动推导出P
有什么办法可以做到这一点吗?
我相信这会奏效:
protocol MyProtocol {
}
struct MyStruct: MyProtocol {
}
class MyClass<P: MyProtocol> {
// added a typealias for P
typealias ContainedProtocol = P
// Required for compiling
required init() {
}
}
class MySpecialClass: MyClass<MyStruct> {
}
// added a default value for protocolType
func foo<P, C: MyClass<P>>(protocolType: P.Type = C.ContainedProtocol.self) -> C {
return C()
}
let specialClass: MySpecialClass = foo()
通过在 MyClass<P: MyProtocol>
中为 P
添加类型别名,我们可以引用该类型。然后我们将其设置为 foo<P, C: MyClass<P>>(protocolType:) -> C
中的默认值。然后,编译器可以从该信息中推断出 P
。
Martin R 的版本似乎和我的一样好,所以选择你最喜欢的那个。他的看起来更简洁一些,因为它不需要 typealias
而且相当简洁。
这里是(之前是评论,现在是答案):
func foo<P, C: MyClass<P>>(dummy: P? = nil) -> C { ... }
正如@Hamish 已经提到的,
func foo<P, C: MyClass<P>>() -> C {
return C()
}
let specialClass: MySpecialClass = foo()
在 Swift 4 中工作。但是 Swift 3 编译器抱怨
error: generic parameter 'P' is not used in function signature
一个可能的解决方法是添加一个类型的虚拟参数
P?
默认值:
func foo<P, C: MyClass<P>>(dummy: P? = nil) -> C {
return C()
}
let specialClass: MySpecialClass = foo()
假设我有这段代码:
protocol MyProtocol {
}
struct MyStruct: MyProtocol {
}
class MyClass<P: MyProtocol> {
// Required for compiling
required init() {
}
}
class MySpecialClass: MyClass<MyStruct> {
}
func foo<P: MyProtocol, C: MyClass<P>>(protocolType: P.Type) -> C {
return C()
}
这样编译调用
let specialClass: MySpecialClass = foo(protocolType: MyStruct.self)
创建类型 MySpecialClass
的实例。
我想要的是不必传入 P
的类型,这样我就可以简单地调用
let specialClass: MySpecialClass = foo()
自动推导出P
有什么办法可以做到这一点吗?
我相信这会奏效:
protocol MyProtocol {
}
struct MyStruct: MyProtocol {
}
class MyClass<P: MyProtocol> {
// added a typealias for P
typealias ContainedProtocol = P
// Required for compiling
required init() {
}
}
class MySpecialClass: MyClass<MyStruct> {
}
// added a default value for protocolType
func foo<P, C: MyClass<P>>(protocolType: P.Type = C.ContainedProtocol.self) -> C {
return C()
}
let specialClass: MySpecialClass = foo()
通过在 MyClass<P: MyProtocol>
中为 P
添加类型别名,我们可以引用该类型。然后我们将其设置为 foo<P, C: MyClass<P>>(protocolType:) -> C
中的默认值。然后,编译器可以从该信息中推断出 P
。
Martin R 的版本似乎和我的一样好,所以选择你最喜欢的那个。他的看起来更简洁一些,因为它不需要 typealias
而且相当简洁。
这里是
func foo<P, C: MyClass<P>>(dummy: P? = nil) -> C { ... }
正如@Hamish 已经提到的,
func foo<P, C: MyClass<P>>() -> C {
return C()
}
let specialClass: MySpecialClass = foo()
在 Swift 4 中工作。但是 Swift 3 编译器抱怨
error: generic parameter 'P' is not used in function signature
一个可能的解决方法是添加一个类型的虚拟参数
P?
默认值:
func foo<P, C: MyClass<P>>(dummy: P? = nil) -> C {
return C()
}
let specialClass: MySpecialClass = foo()