Modifying case class constructor parameter before setting value

China☆狼群 提交于 2019-12-05 01:33:30
wingedsubmariner
abstract case class AbsVal private(value: Double)

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

Abstract case classes don't have an apply method automatically generated in their companion object. This lets us create our own. We have to create another class to inherit from the case class (anonymous, here), but the toString method generated for the case class will still display it as an AbsVal, so this should be invisible as well. A copy method is not automatically generated for abstract case classes, but for a class with a single parameter like this it wouldn't be useful anyway (and it can always be defined manually, see LimbSoup's answer).

Case class inheritance is usually a bad idea, but because of the private constructor the only subclass that will exist will be the anonymous one we define, so in this instance it is safe.

it's annoying to have to litter the code with AbsVal.make(x) instead of just AbsVal(x)

This is an extremely subjective point. Throughout different languages it is a common wisdom to prefer descriptive names to overloaded definitions, since they tend to introduce ambiguity. Yours is a perfect example of such a case.

Hence, AbsVal.make(x) is the correct way to go in your situation. Although I'd rather name it something like AbsVal.abs(x).

There doesn't seem to be a way to override apply on a case class. There are some syntactic errors in your code, but even changing it to override def apply(value: Double): AbsVal = new AbsVal(Math.abs(value)) will fail. I think this behavior is intentional, because when you define AbsVal(-1), you expect the value not to change (for any case class).

Nonetheless, the same feel can be achieved through a class with a private constructor. Obviously a bit more work to get the same functionality as a case class, but your AbsVal.make is gone..

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)

}
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!