2011-04-07 98 views
2

我有一個資源對象存儲在一個選項中。關閉存儲在Option []中的資源

private var ochan: Option[Channel] = None 

在程序執行期間的某一點,ochan設置爲Some(channel)。我想關閉該頻道(通過調用方法close),並在一次致命一擊中將該選項設置爲None

目前我有:

def disconnect = ochan = { ochan.foreach{_.close}; None } 

而且以前我有:

def disconnect = ochan = ochan.flatMap{ o => o.close; None } 

有沒有更好的方式來做到這一點?

+1

你應該澄清一下「更好」對你來說意味着什麼。 – CheatEx 2011-04-08 09:59:28

回答

5

我會寫這樣的:

def disconnect = ochan = ochan match { 
    case Some(ch) => ch.close(); None 
    case None => None // do nothing 
} 

,而不是使用foreachflatMap。在我看來,這個解決方案更清楚明確地顯示了會發生什麼。 foreachflatMap的解決方案需要額外的心智跳躍,您必須知道這些方法在Option上的做法。

+1

我同意foreach和flatMap的心跳問題。 – Andy 2011-04-07 23:10:19

+0

那個不適用於多個線程。 – Anonymous 2011-04-09 15:46:46

0

您可以定義ochan_=,使分配一個新的價值ochan關閉舊的通道(類似於std::auto_ptr<>在C++),但我不知道你是如何封裝在一個子類的Option[Channel],因爲存儲在你的類。該解決方案根本不會改變代碼,它只會通過指定ochan來暗示disconnect

0

我想這可能是工作:

def disconnect { 
    ochan = { 
    ochan.get.close 
    None 
    } 
} 

def disconnect { 
    ochan.get.close 
    ochan = None 
} 

無論如何,因爲有變異操作,總是需要2次調用(1接近,一個用於無分配)。

+0

不要使用'get'方法,它不是類型安全的。 – 2011-04-07 21:01:57

+1

@Jesper Nordenberg我認爲它仍然是「類型安全」,也許「不是無安全」? ('val x:Option [String] = None; x.get' - 編譯好,運行不那麼多) – 2011-04-07 21:10:45

+0

'get'在'None'上調用時會拋出一個運行時異常,使得編譯時間類型不安全。 – 2011-04-07 21:16:57

3

我不知道這是更好,但它是短(一旦你定義的隱含的):

implicit def closer(o: Option[Channel]) = new { 
    def close(): Option[Channel] = { o.foreach(_.close); None } 
} 

def disconnect = ochan = ochan.close 
+0

爲了簡化第一個函數而編寫複製第一個函數的第二個函數似乎對我來說更加複雜......並且可讀性較差。 – 2011-04-08 18:14:58

+0

那個不適用於多個線程。 – Anonymous 2011-04-09 15:47:18

+0

@Anonymous如果這是一個問題,那麼你只需添加同步。我不認爲這在實踐中是一個問題,你很可能不會同時使用多個線程中的同一個通道對象。 – Jesper 2011-04-11 09:47:58

1

不可變var和可變val之間沒有太大區別。那麼爲什麼不把行爲封裝在一個單獨的類中,而當你想要可變性呢?

class ChannelOption { 
    private var _channel :Option[Channel] = None 
    def channel = _channel 
    def channel_=(ch:Option[Channel]) { _channel.foreach(_.close); _channel = ch } 
} 

用法:

private val ochan = new ChannelOption 
ochan.channel = Some(getAChannel) 
ochan.channel.foreach(useChannel) 
ochan.channel = Some(getAnotherChannel) //this automatically closes the first channel 
ochan.channel = None //this automatically closes the second channel 
+0

那個不適用於多個線程。 – Anonymous 2011-04-09 15:47:54

1

它不是線程安全的!請記住,使用@volatile(這裏沒有;採用同步),並且做這樣的事情:(這就是爲什麼我不喜歡命令式代碼)

private val lock = new Object 

def disconnect() {//Function has side effects: remember parenthesis! 
    lock.synchronized { //Synchronizations is important; you don't want to close it multiple times 
    ochan.foreach {_.close()} //Again: side effects -> parens. 
    } 
} 

如果你不使用並行編程,你是做錯事。