当在协议扩展中实现返回Self的静态协议函数时,在扩展中的函数的实现(在没有上下文的情况下显示的最小简化方案)中出现错误:
import Foundation protocol P { static func f() -> Self static func g() -> Self } extension P { static func f() -> Self { // Method 'f()' in non-final class 'NSData' must return `Self` to conform to protocol 'P' return g() } } extension NSData: P { static func g() -> Self { return self.init() } }
用P替换自己的错误发生的原因导致编译器segfault(sig 11)(这似乎是传递类型不匹配错误的有效方式).
将f()的声明更改为返回P,并将错误行上的P替换为P,导致编译成功,但会丢失类型精度(并且需要在每个调用站点强制执行加载,并详细记录自我需求) .
是否有任何其他的解决方法,这个问题不会失去通用返回类型?
编辑:补充缺乏上下文的更多细节:P是一个公共协议,将由库公开,各种类型符合(并覆盖g()),因此在NSData中覆盖f()不是一个选项.最好不要将f()更改为协议扩展以外的其他东西,因为它在多个地方内部由库使用.给定这两个选项,将f()的返回类型更改为P是一个更好的选择.
在Swift 3:
extension Data: P { static func g() -> Data { return self.init() } }
或者你可以用最后的子类替换你的课程:
final class MyData: NSData {} extension MyData: P { ... }
如果NSData是那些不能轻易被子类化的类集群之一(您将看到具有__CFRequireConcreteImplementation的堆栈跟踪),则可能必须为真实的NSData创建一个最终的类包装,而不是使用一个子类.