在设置值之前修改case类构造函数参数

时间:2014-06-16 00:01:55

标签: scala case-class

在Scala成为apply()之前,是否有办法修改传递给单参数案例类构造函数/ val方法的参数? E.g。

case class AbsVal private(aVal: Double)

object AbsVal {
    def apply(aVal: Double): AbsVal = AbsVal(Math.abs(aVal)) // doesn't compile
}

当然,对重载定义的模糊引用失败了。我想也许我可以使用命名参数(以及构造函数vs apply()的不同参数名称)来欺骗它,但这也不起作用。

当然代替apply()我可以使用私有构造函数和工厂方法,但是不得不使用AbsVal.make(x)而不仅仅是{{1}而烦恼代码而烦恼}。

3 个答案:

答案 0 :(得分:5)

abstract case class AbsVal private(value: Double)

object AbsVal {
  def apply(value: Double): AbsVal = new AbsVal(Math.abs(value)) {}
}

抽象案例类没有在其伴随对象中自动生成的apply方法。这让我们创造了自己的。我们必须创建另一个类来继承case案例类(匿名,这里),但为case类生成的toString方法仍然会将其显示为AbsVal,所以这也应该是不可见的。对于抽象案例类,不会自动生成copy方法,但对于具有单个参数的类,无论如何都不会有用(并且总是可以手动定义,请参阅LimbSoup的答案)。

Case类继承通常是a bad idea,但由于私有构造函数,唯一存在的子类将是我们定义的匿名子类,因此在这种情况下它是安全的。

答案 1 :(得分:3)

  使用AbsVal.make(x)而不仅仅是AbsVal(x)

而烦恼的代码令人烦恼

这是一个非常主观的观点。在不同的语言中,优先使用描述性名称来重载定义是一种常见的智慧,因为它们往往会引入歧义。你的是这种情况的完美例子。

因此,AbsVal.make(x)是适合您情况的正确方法。虽然我更喜欢将其命名为AbsVal.abs(x)

答案 2 :(得分:2)

似乎没有办法覆盖案例类的apply。您的代码中存在一些语法错误,但即使将其更改为override def apply(value: Double): AbsVal = new AbsVal(Math.abs(value))也会失败。我认为这种行为是有意的,因为当您定义AbsVal(-1)时,您希望该值不会改变(对于任何案例类)。

尽管如此,通过具有private构造函数的类可以实现相同的感觉。显然,要获得与案例类相同的功能,但是你的AbsVal.make已经消失了......

class AbsVal private(val value: Double) {

    def copy(value: Double = this.value): AbsVal = AbsVal(value)

    def equals(that: AbsVal): Boolean = this.value.equals(that.value)

    override def toString: String = "AbsVal(" + this.value.toString + ")"

}

object AbsVal {

    def apply(value: Double):AbsVal = new AbsVal(Math.abs(value))

    def unapply(a: AbsVal): Option[Double] = Some(a.value)

}