错误:非最终类(“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/