2017-03-09 76 views
0
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?爲什麼我應該使用可選的鏈接?

+0

你'Node'類導致強烈的保留週期,因此內存泄漏。它也沒有理由從NSObject繼承。 – Alexander

回答

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的可選性東西。這種或那種方式仍然需要拆開它。檢查零和(同時)解包它的一種方法是使用如上所示的條件綁定。

其他一些要點:

  • head = newNode無條件地出現在兩個「然後」和if語句的「其他」。因此,它可以被提取出來,並且不需要else塊。
  • 沒有理由說這個類應該從NSObject繼承。
1

head仍然是可選的。在if聲明和您的下一個參考之間可能會變成nil

的妥善解決是安全解開可選:

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 
    } 
} 
+0

沒錯,但是如果讓塊阻塞,我不能在內部突變它,因爲它是一個常量。 –

+0

@sashankaryal對。更新。您需要使用'self.head = ...'來引用該屬性。 – rmaddy

1

雖然你有檢查head不爲零,變量head仍然是可選的,所以你必須使用?解開它。如果您在下列情況下寫的,展開的值將是不可選的,您沒有必要使用?

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