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 }
}
}
我希望它能像这样编译。但事实并非如此。我必须重写代码以使其编译和工作:
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
中的next
的DoublyNode
,并尝试访问previous
的LinkedNode(2)
。问题是,LinkedNode
甚至没有previous
属性!因此,允许您以这种方式使用Self
是不安全的。我认为
DoublyNode
根本不应该继承自LinkedNode
。亚历山大的回答很好地解释了这一点,即,这违反了LSP。可以将这两个类关联起来的一件事是使用协议(protocol):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
}
}