关闭存储在Option []中的资源

时间:2011-04-07 19:54:38

标签: scala resources resource-management

我有一个存储在选项中的资源对象。

 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 }

有更好的方法吗?

6 个答案:

答案 0 :(得分:5)

我会这样写:

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

而不是使用foreachflatMap。在我看来,这个解决方案更明确,更明确地显示了会发生什么。使用foreachflatMap的解决方案需要额外的精神跳跃,您必须知道这些方法对Option执行的操作。

答案 1 :(得分:3)

我不知道它更好但是它更短(一旦你定义了隐含的):

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

def disconnect = ochan = ochan.close

答案 2 :(得分: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

答案 3 :(得分: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.
  }
}

如果你不使用并行编程,那你就做错了。

答案 4 :(得分:0)

您可以定义ochan_=,以便为ochan分配新值会关闭旧频道(类似于C ++中的std::auto_ptr<>),但我不知道如何将其封装在由于存储在您的班级中,因此Option[Channel]的子类。该解决方案根本不会更改代码,只会通过分配disconnect来隐式ochan

答案 5 :(得分:0)

我想这可行:

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

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

无论如何,由于存在变异操作,它总是需要2个调用(1个用于关闭,1个用于分配无)。