Scala属性问题

shj*_*shj 11 scala properties javabeans named-parameters scala-2.8

我还在学习Scala,但我认为有趣的一点是Scala模糊了方法和字段之间的界限.例如,我可以建立一个这样的类......

class MutableNumber(var value: Int)
Run Code Online (Sandbox Code Playgroud)

这里的关键是constructor-argument中的var自动允许我像java中的getter/setter一样使用'value'字段.

// use number...
val num = new MutableNumber(5)
num.value = 6
println(num.value)
Run Code Online (Sandbox Code Playgroud)

如果我想添加约束,我可以通过切换到使用方法代替实例字段来实现:

// require all mutable numbers to be >= 0
class MutableNumber(private var _value: Int) {
    require(_value >= 0)

    def value: Int = _value
    def value_=(other: Int) {
        require(other >=0)
        _value = other
    }
}
Run Code Online (Sandbox Code Playgroud)

由于API不会更改,因此客户端代码不会中断:

// use number...
val num = new MutableNumber(5)
num.value = 6
println(num.value)
Run Code Online (Sandbox Code Playgroud)

我的挂机是添加到Scala-2.8的命名参数功能.如果我使用命名参数,我的API 确实会改变,它确实打破了api.

val num = new MutableNumber(value=5)  // old API
val num = new MutableNumber(_value=5) // new API

num.value = 6
println(num.value)
Run Code Online (Sandbox Code Playgroud)

这有什么优雅的解决方案吗?我应该如何设计我的MutableNumber类,以便以后可以在不破坏API的情况下添加约束?

谢谢!

Rex*_*err 11

您可以使用与案例类相同的技巧:使用伴随对象.

object Example {
  class MutableNumber private (private var _value: Int) {
    require (_value >= 0)
    def value: Int = _value
    def value_=(i: Int) { require (i>=0); _value = i }
    override def toString = "mutable " + _value
  }
  object MutableNumber {
    def apply(value: Int = 0) = new MutableNumber(value)
  }
}
Run Code Online (Sandbox Code Playgroud)

在这里它正在工作(并证明,在构造时,你必须使用对象进行创建,因为构造函数被标记为私有):

scala> new Example.MutableNumber(5)
<console>:10: error: constructor MutableNumber cannot be accessed in object $iw
   new Example.MutableNumber(5)
   ^

scala> Example.MutableNumber(value = 2)
res0: Example.MutableNumber = mutable 2

scala> Example.MutableNumber()
res1: Example.MutableNumber = mutable 0
Run Code Online (Sandbox Code Playgroud)