在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}而烦恼代码而烦恼}。
答案 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)
}