class LinkedNode<T> {
var value: T
var next: Self?
required init(_ value: T) {
self.value = value
}
}
class DoublyNode<T>: LinkedNode<T> {
weak var previous: DoublyNode?
override var next: Self? {
didSet { next.previous = self }
}
}
我希望它能像这样编译。但事实并非如此。
存储的属性不能具有协变“Self”类型
我必须重写代码才能使其编译并工作:
class LinkedNode<T> {
var value: T
var next: LinkedNode?
required init(_ value: T) {
self.value = value
}
}
class DoublyNode<T>: LinkedNode<T> {
weak var previous: DoublyNode?
override var next: LinkedNode<T>? {
didSet { (next as! Self).previous = self }
}
}
并且在后面的代码中处处每次引用后next
属性我必须手动将其转换为 DoublyNode(当我使用 DoublyNode 时),因为它始终具有 LinkedNode 类型。
它是可以管理的,但又烦人又丑陋。
让我演示一下为什么 Swift 不允许这样做。如果它确实允许您使用Self
这样,理论上你可以这样做:
let doublyNode = DoublyNode(1)
let linkedNode: LinkedNode<Int> = doublyNode // this assignment should work, right?
linkedNode.next = LinkedNode(2) // "linkedNode" is of type LinkedNode, so Self is LinkedNode, so I can do this assignment, right?
现在会发生什么?这didSet
of next
in DoublyNode
被调用,它尝试访问previous
of LinkedNode(2)
。事情是,LinkedNode
甚至没有previous
财产!因此,允许您使用Self
这种方式不安全。
我不认为DoublyNode
应该继承自LinkedNode
根本不。亚历山大的回答很好地解释了这一点,即这违反了LSP https://en.wikipedia.org/wiki/Liskov_substitution_principle。您可以做的一件事是使用协议来关联这两个类:
protocol LinkedNodeProtocol {
associatedtype Data
var value: Data { get set }
var next: Self? { get set }
init(_ value: Data)
}
final class LinkedNode<Data>: LinkedNodeProtocol {
var value: Data
var next: LinkedNode?
init(_ value: Data) {
self.value = value
}
}
final class DoublyNode<Data>: LinkedNodeProtocol {
var value: Data
weak var previous: DoublyNode?
var next: DoublyNode? {
didSet { next?.previous = self }
}
init(_ value: Data) {
self.value = value
}
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)