在检查变量不是nil后,为什么还要再次使用可选链接?

时间:2017-03-09 03:33:36

标签: swift

class LinkedList : NSObject
{
    var head : Node?
    var tail : Node?

    func insertAtHead( newNode : Node )
    {
        if (head != nil) {
            newNode.next = head
            head?.prev = newNode
            head = newNode
        }
        else {
            head = newNode
        }
    }
}

我的节点类是:

class Node : NSObject
{
    var value : Int = 0
    var next : Node?
    var prev : Node?
}

我对insertAtHead方法中的行head?.prev = newNode感到困惑。我已经检查并确认头部不是零,为什么我不能在这种情况下键入head.prev = newNode?我为什么要使用可选链接?

3 个答案:

答案 0 :(得分:2)

你不应该,这是一个常见的Swift反模式。试试这个:

class LinkedList {
    var head: Node?
    var tail: Node?

    func insertAtHead(newNode: Node) {
        if let head = head {
            newNode.next = head
            head.prev = newNode
        }

        head = newNode
    }
}

简单地与nil进行比较,对head的可选性无效。你仍然需要以这种或那种方式解开它。检查nil和(同时)打开它的一种方法是使用如上所示的条件绑定。

其他几点:

  • head = newNode无条件地出现在if语句的“then”和“else”中。因此,它可以被提取出来,并且不再需要else块。
  • 这个类没有理由继承NSObject

答案 1 :(得分:1)

head仍然是可选的。它可能会在nil语句与您的下一个引用之间变为if

正确的解决方案是安全地展开可选项:

func insertAtHead( newNode : Node )
{
    if let thead = head {
        newNode.next = thead
        thead.prev = newNode
        self.head = newNode
    } else {
        head = newNode
    }
}

我使用了不同的变量名来说清楚。你实际上可以这样做:

func insertAtHead( newNode : Node )
{
    if let head = head {
        // head in here is actually a new variable (with the same name)
        newNode.next = head
        head.prev = newNode
        self.head = newNode
    } else {
        head = newNode
    }
}

答案 2 :(得分:1)

虽然您已检查head不是nil,但变量head仍然是可选的,因此您必须使用?打开它。如果您在以下情况下撰写,则展开的值将是非可选的,您无需使用?

func insertAtHead( newNode : Node )
{
    if let head = head {
        newNode.next = head
        head.prev = newNode
        head = newNode
    }
    else {
        head = newNode
    }
}