如何实现返回协变Selfs的协议方法?

Jes*_*ssy 5 inheritance protocols swift

错误:协议'协议'要求'实例'不能被非最终类('Class')满足,因为它在非参数非结果类型位置使用'Self'

protocol Protocol {
    var instance: Self {get}
}

class Class: Protocol {
    var instance: Class {return Subclass()}
}

class Subclass: Class {}
Run Code Online (Sandbox Code Playgroud)

以下是我在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 {}
Run Code Online (Sandbox Code Playgroud)

...在未来版本的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 {}
Run Code Online (Sandbox Code Playgroud)

我是如何模仿与我的问题相关的部分:

protocol Protocol: ProtocolInstance {
    static var instance: ProtocolInstance {get}
}

protocol ProtocolInstance {}


class Class: Protocol {
    static var instance: ProtocolInstance {return Subclass()}
}

class Subclass: Class {}
Run Code Online (Sandbox Code Playgroud)

而且,我认为这是我的代码的相关部分:

protocol Protocol {
    static var : Self? {get} // an existing instance? 
    static var : Self {get}  // a new instance

    func instanceFunc()
}

extension Protocol {
    static func staticFunc() {
        ( ?? ).instanceFunc()
    }
}
Run Code Online (Sandbox Code Playgroud)

Rob*_*ier 7

正如它所说,你不能这样做,并且有充分的理由.你不能证明你会信守诺言.考虑一下:

class AnotherSubclass: Class {}
let x = AnotherSubclass().instance
Run Code Online (Sandbox Code Playgroud)

所以x应该AnotherSubclass根据你的协议(那是Self).但它实际上是Subclass,这是一种完全不同的类型.除非上课,否则你无法解决这个悖论final.这不是斯威夫特的限制.这种限制将存在于任何正确的类型系统中,因为它允许类型矛盾.

另一方面,你可以做的是承诺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
Run Code Online (Sandbox Code Playgroud)

现在x是明确的类型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 {}
Run Code Online (Sandbox Code Playgroud)

这避免了继承问题(你不能以AnotherClass这种方式创建相同的" 返回错误的类型").