我写了这个类:
class Queue<T> {
var value: T
var next: Queue<T>?
init(_ items: Any...)
{
self.value = items[0]
}
但是我想知道有没有办法通过为参数"value"设置一些默认值来实现构造函数。我知道如果我把它贴花为" var value: T?" 没问题,但是是否有任何"黑客"解决方案与构造函数中的当前代码设置一些默认值,它是什么并不重要,因为我想制作这样的对象:var obj = Queue((,导致当前 Queue(( 崩溃
如果您确定将设置值并且不想处理 Optionals,则可以使用!
来声明隐式解包的 Optional
class Queue<T> {
var value: T!
// ...
}
这里有更多关于这方面的 docs.swift.org
您在这里犯的设计错误是您将链表中的节点公开为公共 API。您的Queue<T>
类对节点进行建模,当然,链接列表节点必须包含一个值。否则,它不是列表的真正节点,是吗?
相反,您应该有一个父LinkedList
(或Queue
,在您的例子中(结构,它封装了对头/尾LinkedListNode
的引用。这样,可以使用LinkedList.head
的nil
值对空列表进行建模。
以下是我将如何做到这一点:
struct LinkedList<T> {
class Node {
let value: T
let next: Node?
init(value: T, next: Node?) {
self.value = value
self.next = next
}
convenience init?(head: T?, tail: ArraySlice<T>) {
guard let head = head else { return nil }
self.init(
value: head,
next: Node(head: tail.first, tail: tail.dropFirst())
)
}
}
var head: Node?
init(_ elements: T...) {
self.init(elements)
}
// ugh, you can't forward a vararg in Swift, so you need to have this overload >_>
init(_ elements: [T]) {
self.head = Node(head: elements.first, tail: elements.dropFirst())
}
}
extension LinkedList: CustomStringConvertible {
var description: String {
guard let head = self.head else { return "LinkedList[empty]"}
let allNodes = sequence(first: head, next: { $0.next })
let body = allNodes
.map { String(describing: $0.value) }
.joined(separator: ", ")
return "LinkedList[(body)]"
}
}
print(LinkedList(1, 2, 3)) // => LinkedList[1, 2, 3]
然后我会将Queue<T>
实现为一个围绕LinkedList<T>
的基本包装器
struct Queue<T> {
var list: LinkedList<T>
init(_ initialElements: T...) {
self.list = LinkedList(initialElements)
}
mutating func push(_ newElement: T) {
let newHead = LinkedList.Node(value: newElement, next: self.list.head)
self.list.head = newHead
}
mutating func pop() -> T? {
guard let head = self.list.head else { return nil }
self.list.head = head.next
return head.value
}
}
var q = Queue(3, 2, 1)
print(q) // => Queue<Int>(list: LinkedList[3, 2, 1])
q.push(4); print(q) // => Queue<Int>(list: LinkedList[4, 3, 2, 1])
q.push(5); print(q) // => Queue<Int>(list: LinkedList[5, 4, 3, 2, 1])
print(q.pop(), q) // => Optional(5) Queue<Int>(list: LinkedList[4, 3, 2, 1])
print(q.pop(), q) // => Optional(4) Queue<Int>(list: LinkedList[3, 2, 1])
print(q.pop(), q) // => Optional(3) Queue<Int>(list: LinkedList[2, 1])
print(q.pop(), q) // => Optional(2) Queue<Int>(list: LinkedList[1])
print(q.pop(), q) // => Optional(1) Queue<Int>(list: LinkedList[empty])
print(q.pop(), q) // => nil Queue<Int>(list: LinkedList[empty])