我面临的问题是 T 无法在 MyThing 的情况下推断出来。当涉及到错误消息时,编译器并不是很有帮助(有一次我被告知Cannot convert return expression of type 'T' (aka 'MyImplementation') to return type 'T')
解决方案是提供某种方式让编译器知道T 应该是什么(如果您希望它不受约束,请使用AnyObject,而不是T)。
在我的例子中,我想返回一个 Self 类型的值(实现的类型)。这比正常的 POP 问题更复杂,因为您不能在类/静态函数中引用 Self。
为了解决这个问题,我使用了 Swift 的 associatedtype,它允许我们设置一个命名的占位符以跨协议使用。由于我们在协议级别定义它并提供一个值,因此我们可以为实现者自己的类型设置一个命名引用。
associatedtype MyType = Self.Type
注意 associatedtype MyType = Self 不起作用,因为 self 在这种情况下是协议,而不是最终实现的类型(我们还不知道,并且我们/编译器在某些对象实际实现协议之前不会知道)。
由于我们提供了一个值,所以当我们实现我们的协议时,类型已经受到限制!由于约束仅涉及实现的类型,因此实现协议足以定义类型(酷)。最好的部分是现在我可以在我的class func 定义中消除对 Self 的引用:
protocol MakesSelf {
associatedtype MyType = Self.Type
static func getInstance() -> MyType
}
class MyImplementation: MakesSelf {
class func getInstance() -> MyImplementation {
print("Hello")
return MyImplementation()
}
}
let myThing = MyImplementation.getInstance()
在这里要超级清楚 - MyImplementation 类有一个名为 MyType 的类型别名,由协议指定。当我编译时,别名将引用当前的实现。现在,当我实现函数 getInstance 时,MyImplementation 符合 MyType。
注意,我必须以class func getInstance() -> MyImplementation 的形式编写我的函数签名,而不是class func getInstance() -> MyType。这是因为我正在返回函数调用 MyImplementation() 的结果,它恰好符合 MyType 的约束。这与说 MyImplementation 可以通过隐式转换为 MyType 不同。
关于尝试制作protocol function specification for returning self see here的好书,但我想发布具体的解决方案和解释。