错误:非最终类(’Class’)无法满足协议’Protocol’要求’instance’,因为它在非参数,非结果类型位置使用’Self’
protocol Protocol { var instance: Self {get} } class Class: Protocol { var instance: Class {return Subclass()} } class Subclass: Class {}
这就是我用C#表达我想要的方式。(据我所知,C#无法强制通用参数“ Self”实际上是我们从Swift知道的Self,但是它的功能足以使我做正确的事情。)
interface Protocol<Self> where Self: Protocol<Self> { Self instance {get;} } class Class: Protocol<Class> { public Class instance {get {return new Subclass();}} } class Subclass: Class {}
…在Swift的未来版本中可能看起来如何:
protocol Protocol { typealias FinalSelf: Protocol where FinalSelf.FinalSelf == FinalSelf var instance: FinalSelf {get} } class Class: Protocol { var instance: Class {return Subclass()} } class Subclass: Class {}
我如何模拟与我的问题相关的部分:
protocol Protocol: ProtocolInstance { static var instance: ProtocolInstance {get} } protocol ProtocolInstance {} class Class: Protocol { static var instance: ProtocolInstance {return Subclass()} } class Subclass: Class {}
而且,我相信这是代码的相关部分:
protocol Protocol { static var 🎁: Self? {get} // an existing instance? static var 🐥: Self {get} // a new instance func instanceFunc() } extension Protocol { static func staticFunc() { (🎁 ?? 🐥).instanceFunc() } }
正如它所说,您不能这样做,这是有充分理由的。您无法证明自己会信守诺言。考虑一下:
class AnotherSubclass: Class {} let x = AnotherSubclass().instance
因此,x应AnotherSubclass根据您的协议(即Self)进行操作。但实际上是Subclass,这是完全不同的类型。除非课程是,否则您无法解决这个悖论final。这不是Swift的限制。此限制在任何正确的类型系统中都将存在,因为它允许类型矛盾。
x
AnotherSubclass
Self
Subclass
final
另一方面,您可以做的是保证instance在所有子类(即超类)中返回某种一致的类型。您可以使用关联的类型来执行此操作:
instance
protocol Protocol { typealias InstanceType var instance: InstanceType {get} } class Class: Protocol { var instance: Class {return Subclass()} } class Subclass: Class {} class AnotherSubclass: Class {} let x = AnotherSubclass().instance
现在x无疑是type Class。(它也碰巧是随机的其他子类,这很奇怪,但这就是代码所说的。)
Class
顺便说一句,所有这些通常表明您确实应该使用子类化。组合和协议可能会在Swift中更好地解决此问题。问问自己,是否有任何Subclass实际需要成为的子类的原因Class。可以是符合相同协议的独立类型吗?当您摆脱子类并专注于协议时,各种问题都会消失。
我一直在考虑这个问题,也许可以找到您想要的东西。与其说所有子类都实现instance,instance不如将其作为扩展。如果您想返回其他内容,您仍然可以覆盖它。
protocol Protocol { init() } class Class: Protocol { required init() {} var instance: Class { return Subclass() } } extension Protocol { var instance: Self { return self.dynamicType.init() } } class Subclass: Class {}
这避免了继承问题(您不能通过AnotherClass这种方式创建相同的“ 返回错误的类型”)。
AnotherClass