假设我有这段代码:
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将自动推断出来。
有没有办法让这种情况发生?
答案 0 :(得分:2)
我相信这会奏效:
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()
通过在P
中添加MyClass<P: MyProtocol>
的类型,我们可以引用该类型。然后我们将其设置为foo<P, C: MyClass<P>>(protocolType:) -> C
中的默认值。然后,编译器可以从该信息中推导出P
。
Martin R的版本似乎与我的版本一样好,所以请选择你最喜欢的版本。他似乎有点清洁,因为它不需要typealias
而且相当简洁。
这是his(这是评论,现在是答案):
func foo<P, C: MyClass<P>>(dummy: P? = nil) -> C { ... }
答案 1 :(得分:2)
正如@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()