嵌套泛型的快速函数

时间:2017-06-20 20:24:25

标签: swift generics swift3 swift-protocols

假设我有这段代码:

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将自动推断出来。

有没有办法让这种情况发生?

2 个答案:

答案 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()