swift - 如何实现返回协变 Selfs 的协议(protocol)方法?

标签 swift inheritance protocols

错误:非最终类(“Class”)无法满足协议(protocol)“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 的 future 版本中会是什么样子:

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()
    }
}

最佳答案

正如它所说,您不能这样做,并且有充分的理由。你无法证明你会信守 promise 。考虑一下:

class AnotherSubclass: Class {}
let x = AnotherSubclass().instance

因此根据您的协议(protocol)(即Self),x 应该是AnotherSubclass。但它实际上是 Subclass,这是一种完全不同的类型。除非该类是 final,否则您无法解决这个悖论。这不是 Swift 的限制。这种限制将存在于任何正确的类型系统中,因为它允许类型矛盾。

另一方面,您可以 promise instance 在所有子类(即父类(super class))中返回某种一致的类型。您可以使用关联类型执行此操作:

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 明确属于 Class 类型。 (它也恰好是随机的其他子类,这有点奇怪,但这就是代码所说的。)

顺便说一句,所有这些通常表明您在不应该使用子类化的情况下使用了子类化。组合和协议(protocol)可能会在 Swift 中更好地解决这个问题。问问自己是否有任何理由 Subclass 实际上需要成为 Class 的子类。会不会是一个独立的类型,符合相同的协议(protocol)?当您摆脱子类并专注于协议(protocol)时,各种问题都会消失。


我一直在思考这个问题,也许有一种方法可以得到你要找的东西。与其说所有子类都实现 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 返回错误的类型”)。

关于swift - 如何实现返回协变 Selfs 的协议(protocol)方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32999293/

相关文章:

ios - 在 Swift 中类作为函数参数

swift - 警告 : Attempt to present ViewController on ViewController which is already presenting ViewController

c# - 继承窗体上的 OnLoad 事件不会被调用

c++ - 面向对象 C++ : Which pattern: 2 classes with the partly same methods

javascript - JavaScript 书签是否必须是有效的 URL?

html - 没有http协议(protocol)的链接

ios - 如何分三个阶段处理 slider ?

ios - 点击 ParentViewController 关闭 ChildViewController

c++ - C++ 中方法参数类型的静态自省(introspection)

swift - 协议(protocol)关联类型类型别名分配编译错误