Gre*_*reg 17 interface swift swift2 protocol-extension
当实现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()
    }
}
更换Self与P上发生错误的行使编译器段错误(SIG 11)(这似乎输送类型不匹配错误的有效的方式).
改变的申报f()返回P,以及更换Self用P的错误行,结果在编译成功,但失去式精密(并且需要力向下转换在每次调用点,再加上记录了Self详细要求).
是否有任何其他解决方法可以解决此问题,并且不会丢失通用返回类型?
编辑:进一步的细节,以补偿缺少上下文的:P是一个公共协议,它由库被暴露,用于各种类型的,以符合(和覆盖g()),所以覆盖f()在NSData不是一个选项.最好不必更改f()为协议扩展之外的其他内容,因为库内部在许多地方使用它.鉴于这两个选项,更改f()to 的返回类型P是一个更好的选择.
从Swift 4(可能是3)开始,上面的代码按原样运行.
在 Swift 3 或 4 中:
import Foundation
protocol P {
    static func f() -> Self
    static func g() -> Self
}
extension P {
    static func f() -> Self {
        return g()
    }
}
extension Data: P {
    static func g() -> Data {
        return self.init()
    }
}
或者你可以用最终的子类替换你的类:
import Foundation
protocol P {
    static func f() -> Self
    static func g() -> Self
}
extension P {
    static func f() -> Self {
        return g()
    }
}
import Foundation
final class MyData: NSData {}
extension MyData: P {
    static func g() -> Self {
        return self.init()
    }
}
如果 NSData 是那些不能轻易被子类化的类簇之一(你会看到一个带有 的堆栈跟踪__CFRequireConcreteImplementation),你可能必须为真正的 NSData 创建一个最终的类包装器,而不是使用子类。
| 归档时间: | 
 | 
| 查看次数: | 4101 次 | 
| 最近记录: |