非final类中的方法必须返回`Self`以符合协议

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()
    }
}
Run Code Online (Sandbox Code Playgroud)

更换SelfP上发生错误的行使编译器段错误(SIG 11)(这似乎输送类型不匹配错误的有效的方式).

改变的申报f()返回P,以及更换SelfP的错误行,结果在编译成功,但失去式精密(并且需要力向下转换在每次调用点,再加上记录了Self详细要求).

是否有任何其他解决方法可以解决此问题,并且不会丢失通用返回类型?

编辑:进一步的细节,以补偿缺少上下文的:P是一个公共协议,它由库被暴露,用于各种类型的,以符合(和覆盖g()),所以覆盖f()NSData不是一个选项.最好不必更改f()为协议扩展之外的其他内容,因为库内部在许多地方使用它.鉴于这两个选项,更改f()to 的返回类型P是一个更好的选择.

更新

从Swift 4(可能是3)开始,上面的代码按原样运行.

Jan*_*ano 5

在 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()
    }
}
Run Code Online (Sandbox Code Playgroud)

或者你可以用最终的子类替换你的类:

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()
    }
}
Run Code Online (Sandbox Code Playgroud)

如果 NSData 是那些不能轻易被子类化的类簇之一(你会看到一个带有 的堆栈跟踪__CFRequireConcreteImplementation),你可能必须为真正的 NSData 创建一个最终的类包装器,而不是使用子类。