错误:协议'协议'要求'实例'不能被非最终类('Class')所满足,因为它在非参数非结果类型位置使用'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()
}
}
答案 0 :(得分:7)
正如它所说,你不能这样做,而且有充分的理由。你不能证明你会信守诺言。考虑一下:
class AnotherSubclass: Class {}
let x = AnotherSubclass().instance
因此,根据您的协议(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
现在x
明确是Class
类型。 (它也恰好是随机的其他子类,这有点奇怪,但这就是代码所说的。)
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
返回错误的类型”。
答案 1 :(得分:2)
如果您不想为每个子类实际返回Self
,这实际上是有意义的并且有效:
protocol Protocol : class {
typealias Sub : Self
var instance: Sub {get}
}
这意味着您的协议定义了一个必须是其自身子类的类型。以下代码可以正常工作:
class Class: Protocol {
var instance: Class {return Subclass()}
}
class Subclass: Class {}
Class().instance // Returns SubClass()
但是上面的代码没有使用错误编译
error: inheritance from non-protocol, non-class type '`Self`'
我认为这是一个错误,因为Self
被声明为类类型。但是你可以这样做:
protocol Protocol : class {
typealias Sub : Class
var instance: Sub {get}
}
但是你没有太多的协议本身,因为只有类本身应该符合它。