构造函数调用期间和对象创建后的参数验证

时间:2012-06-02 09:48:22

标签: validation scala parameters

我想检查构造函数参数并拒绝构造抛出IllegalArgumentException,以防参数集无效(值不符合预期约束)。在修改对象时设置相同的参数集时,同样的检查应该有效。如何在Scala中编写代码?

  scala> class Rectangle (var Length:Double, var Width:Double){
   | if (Length <0)
   | throw new IllegalArgumentException("The Length must be Non-negative")
   | if (Width <0)
   | throw new IllegalArgumentException("The Width must be Non-negative")
   | def setLength(l:Double) = Length = l
   | }
  defined class Rectangle

  scala> var R = new Rectangle (-9, -9)
  java.lang.IllegalArgumentException: The Length must be Non-negative
at Rectangle.<init>(<console>:9)

  scala> var R = new Rectangle (0, -9)
  java.lang.IllegalArgumentException: The Width must be Non-negative
at Rectangle.<init>(<console>:11)



   scala> var R = new Rectangle(9, 9)
   R: Rectangle = Rectangle@1590164


   scala> R.Length
   res7: Double = 9.0

   scala> R.Width
   res8: Double = 9.0

   scala> R.setLength(18)

   scala> R.Length
   res10: Double = 18.0

   scala> R.setLength(-9)
   // R.setLength should not the set the Length to -9.   **************************
   scala> R.Length
   res12: Double = -9.0

4 个答案:

答案 0 :(得分:2)

您需要一个属性设置器/ getter方法。

class Rectangle(private var l: Int, private var w: Int) {
  require(l > 0, "Invalid length: " + l + " <0 ")
  require(w > 0, "Invalid width: " + w + " <0 ")
  def length = l
  def width = w
  def length_=(len: Int) { require(len > 0, "Invalid length: " + len + " < 0"); l = len }
  def width_=(wid: Int) { require(wid > 0, "Invalid width: " + wid + " < 0"); w = wid }
  override def toString = length + ", " + width
}

答案 1 :(得分:2)

一定是可变的吗?

case class Rectangle(length:Double, width:Double) {
  if (length < 0)
    throw new IllegalArgumentException("The Length must be Non-negative")
  if (width < 0)
    throw new IllegalArgumentException("The Width must be Non-negative")
  def setLength(l: Double) = copy(length=l)
}

答案 2 :(得分:2)

可变状态是一个坏主意,但如果你确实需要并且不需要两点验证,你可以使用稍微修改过的 Prince John Wesley 的解决方案:

class Rectangle(l: Int, w: Int) {

  private[this] var _length: Int = _
  private[this] var _width: Int = _
  def length: Int = _length
  def width: Int = _width
  def length_=(len: Int) { require(len > 0, "Invalid length: " + len + " < 0"); _length = len }
  def width_=(wid: Int) { require(wid > 0, "Invalid width: " + wid + " < 0"); _width = wid }

  length = l
  width = w

  override def toString = length + ", " + width
}

答案 3 :(得分:2)

我不喜欢到目前为止提到的答案。您的问题是参数必须有效才能创建对象。其他解决方案中止对象创建,但在我看来,你真正想要的不是堕胎,而是在创建对象之前进行一些检查。要实现这一点,你需要工厂:

object Rectangle {
  def apply(length:Double, width:Double): Rectangle = {
    require(length >= 0, "The Length must be Non-negative")
    require(width >= 0, "The Width must be Non-negative")
    new Rectangle(length, width)
  }
}
class Rectangle private(val length:Double, val width:Double) {
  def length_=(l: Double) = Rectangle(l, width)
}

这里唯一的问题是,当我们想要定义自己的apply-Method(与类构造函数具有相同的方法签名)时,我们不允许创建case类。