Scala 关闭存储在选项[]中的资源

Scala 关闭存储在选项[]中的资源,scala,resources,resource-management,Scala,Resources,Resource Management,我有一个资源对象存储在一个选项中 private var ochan: Option[Channel] = None 在程序执行过程中的某个时刻,ochan被设置为some(通道)。我想关闭频道(通过调用方法close)并在一次致命一击中将选项设置为None 目前我有: def disconnect = ochan = { ochan.foreach{_.close}; None } 以前我有: def disconnect = ochan = ochan.flatMap{ o =&g

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

 private var ochan: Option[Channel] = None
在程序执行过程中的某个时刻,
ochan
被设置为
some(通道)
。我想关闭频道(通过调用方法
close
)并在一次致命一击中将选项设置为
None

目前我有:

 def disconnect = ochan = { ochan.foreach{_.close}; None }
以前我有:

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

有更好的方法吗?

您可以定义
ochan
,这样给
ochan
分配一个新值就会关闭旧通道(类似于C++中的
std::auto\u ptr
),但我不知道如何将其封装在
选项[channel]
的子类中,因为存储在您的类中。该解决方案根本不会对代码进行太多更改,它只会通过分配
ochan

使
断开连接
隐式化,我想这可能会起作用:

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


无论如何,由于存在变异操作,它将始终需要两个调用(一个用于关闭,一个用于无赋值)。

我不知道它是否更好,但它更短(一旦定义了隐式):


我会这样写:

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

而不是使用
foreach
flatMap
。在我看来,这个解决方案更清楚、更明确地显示了发生了什么。使用
foreach
flatMap
的解决方案需要额外的思维跳跃,您必须知道这些方法在
选项上做了什么

不可变的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

它不是线程安全的!记住使用@volatile(这里不使用;使用同步),并执行如下操作:(这就是我不喜欢命令式代码的原因)


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

不要使用
get
方法,它不是类型安全的。@Jesper Nordenberg我认为它仍然是“类型安全的”,也许是“不安全的”?(
val x:Option[String]=None;x.get
--编译良好,运行不太频繁)
get
在调用
None
时将引发运行时异常,使其编译时类型不安全。@Jesper Nordenberg参见上文。现在仍然是<代码> null .Strase[String ]。长度可以说是类型化的(尽管我可能在这里用“代码> > <代码>的方式推动边界”,前面的注释在我所理解的类型安全的范围内是很好的,但是)Jesper Nordenberg考虑<代码> ValApdio= GETunNeNoNoopOnter();someOption.get
类似于
valy:Int=getUnknown();val z=1/y
(其中
someOption
是Some/None还是
y
是0/non-0不得而知)我同意foreach和flatMap的精神跳跃问题。你应该澄清什么是“更好的”写第二个函数来复制第一个函数以简化第一个函数对我来说似乎更复杂。。。而且可读性较差。@Anonymous如果这是一个问题,那么您只需添加同步。我不认为这在实践中是一个问题,您很可能不会同时从多个线程使用同一个通道对象。
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
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.
  }
}