2011-04-07 45 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. 
    } 
} 

如果你不使用并行编程,你是做错事。