您如何实现 return 协变 Selfs 的协议方法?
How do you implement protocol methods that return covariant Selfs?
错误:协议 'Protocol' 要求 'instance' 不能被非最终 class ('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()
}
}
如其所说,您不能这样做,并且有充分的理由。你无法证明你会信守诺言。考虑一下:
class AnotherSubclass: Class {}
let x = AnotherSubclass().instance
所以根据您的协议 x
应该是 AnotherSubclass
(即 Self
)。但它实际上是 Subclass
,这是完全不同的类型。除非 class 是 final
,否则您无法解决这个悖论。这不是 Swift 限制。这种限制将存在于任何正确的类型系统中,因为它允许类型矛盾。
另一方面,您可以做的是保证 instance
return 在所有子class 中(即超级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
类型。 (它也恰好是随机的其他子class,这有点奇怪,但这就是代码所说的。)
顺便说一句,所有这些通常表明您在不应该使用 subclassing 的情况下使用。组合和协议可能会在 Swift 中更好地解决这个问题。问问自己是否有任何理由 Subclass
实际上需要成为 Class
的子 class。会不会是一个独立的类型,符合相同的协议?当您摆脱 subclasses 并专注于协议时,各种问题都会消失。
我一直在考虑这个问题,也许有一种方法可以得到你想要的东西。与其说所有子 class 都实现 instance
,不如将 instance
作为扩展附加。如果你想 return 其他东西,你仍然可以覆盖它。
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
return类型错误”)。
如果您不想像这样对每个子 class 实际上 return Self
return Self
,这实际上是有意义的并且有效:
protocol Protocol : class {
typealias Sub : Self
var instance: Sub {get}
}
这意味着您的协议定义了一个类型别名,它必须是其自身的子class。以下代码将起作用:
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
被声明为 class 类型。但是你可以让它以某种方式像这样工作:
protocol Protocol : class {
typealias Sub : Class
var instance: Sub {get}
}
但是你没有太多的协议本身,因为只有 class 本身应该符合它。
错误:协议 'Protocol' 要求 'instance' 不能被非最终 class ('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()
}
}
如其所说,您不能这样做,并且有充分的理由。你无法证明你会信守诺言。考虑一下:
class AnotherSubclass: Class {}
let x = AnotherSubclass().instance
所以根据您的协议 x
应该是 AnotherSubclass
(即 Self
)。但它实际上是 Subclass
,这是完全不同的类型。除非 class 是 final
,否则您无法解决这个悖论。这不是 Swift 限制。这种限制将存在于任何正确的类型系统中,因为它允许类型矛盾。
另一方面,您可以做的是保证 instance
return 在所有子class 中(即超级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
类型。 (它也恰好是随机的其他子class,这有点奇怪,但这就是代码所说的。)
顺便说一句,所有这些通常表明您在不应该使用 subclassing 的情况下使用。组合和协议可能会在 Swift 中更好地解决这个问题。问问自己是否有任何理由 Subclass
实际上需要成为 Class
的子 class。会不会是一个独立的类型,符合相同的协议?当您摆脱 subclasses 并专注于协议时,各种问题都会消失。
我一直在考虑这个问题,也许有一种方法可以得到你想要的东西。与其说所有子 class 都实现 instance
,不如将 instance
作为扩展附加。如果你想 return 其他东西,你仍然可以覆盖它。
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
return类型错误”)。
如果您不想像这样对每个子 class 实际上 return Self
return Self
,这实际上是有意义的并且有效:
protocol Protocol : class {
typealias Sub : Self
var instance: Sub {get}
}
这意味着您的协议定义了一个类型别名,它必须是其自身的子class。以下代码将起作用:
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
被声明为 class 类型。但是你可以让它以某种方式像这样工作:
protocol Protocol : class {
typealias Sub : Class
var instance: Sub {get}
}
但是你没有太多的协议本身,因为只有 class 本身应该符合它。