-1

I'm trying to understand a Scala case class difference with a regular class.

E.g. I have a definition

case class Charge(cc: CreditCard, amount: Double)

and can use it like carge.cc and charge.amount.

Are these statements constant field references or actually hidden getters are used? Is it possible to redefine semantic of e.g. carge.cc to add some code before returning value?

Andriy Kryvtsun
  • 3,220
  • 3
  • 27
  • 41
  • There are various good online documentation about case class, as the ["official" one](http://docs.scala-lang.org/tutorials/tour/case-classes.html) to start with – cchantep Aug 01 '17 at 15:30
  • @cchantep I've already read it and couldn't get an answers to my questions. – Andriy Kryvtsun Aug 01 '17 at 15:31

2 Answers2

1

Case class is a "product type". Think of it as tuple, with elements named, rather than indexed. Technically, yes, cc is a generated accessor function, but no you cannot redefine it. If you could, it would defeat the purpose of it being a case class to begin with.

Just do something like this instead:

class Charge(_cc: CreditCard, _amount: Double) {
  def cc = modify(_cc)
  def amount = addTips(_amount)
}
Dima
  • 39,570
  • 6
  • 44
  • 70
0

Create your file Charge.scala with the content of your code and then compile the code using scalac -print Charge.scala and you will get:

[syntax trees at end of                   cleanup]] // Test.scala
package <empty> {
  case class Charge extends Object with Product with Serializable {
    <caseaccessor> <paramaccessor> private[this] val cc: Int = _;
    <stable> <caseaccessor> <accessor> <paramaccessor> def cc(): Int = Charge.this.cc;
    <caseaccessor> <paramaccessor> private[this] val amount: Double = _;
    <stable> <caseaccessor> <accessor> <paramaccessor> def amount(): Double = Charge.this.amount;
    <synthetic> def copy(cc: Int, amount: Double): Charge = new Charge(cc, amount);
    <synthetic> def copy$default$1(): Int = Charge.this.cc();
    <synthetic> def copy$default$2(): Double = Charge.this.amount();
    override <synthetic> def productPrefix(): String = "Charge";
    <synthetic> def productArity(): Int = 2;
    <synthetic> def productElement(x$1: Int): Object = {
      case <synthetic> val x1: Int = x$1;
      (x1: Int) match {
        case 0 => scala.Int.box(Charge.this.cc())
        case 1 => scala.Double.box(Charge.this.amount())
        case _ => throw new IndexOutOfBoundsException(scala.Int.box(x$1).toString())
      }
    };
    override <synthetic> def productIterator(): Iterator = runtime.this.ScalaRunTime.typedProductIterator(Charge.this);
    <synthetic> def canEqual(x$1: Object): Boolean = x$1.$isInstanceOf[Charge]();
    override <synthetic> def hashCode(): Int = {
      <synthetic> var acc: Int = -889275714;
      acc = Statics.this.mix(acc, Charge.this.cc());
      acc = Statics.this.mix(acc, Statics.this.doubleHash(Charge.this.amount()));
      Statics.this.finalizeHash(acc, 2)
    };
    override <synthetic> def toString(): String = ScalaRunTime.this._toString(Charge.this);
    override <synthetic> def equals(x$1: Object): Boolean = Charge.this.eq(x$1).||({
  case <synthetic> val x1: Object = x$1;
  case5(){
    if (x1.$isInstanceOf[Charge]())
      matchEnd4(true)
    else
      case6()
  };
  case6(){
    matchEnd4(false)
  };
  matchEnd4(x: Boolean){
    x
  }
}.&&({
      <synthetic> val Charge$1: Charge = x$1.$asInstanceOf[Charge]();
      Charge.this.cc().==(Charge$1.cc()).&&(Charge.this.amount().==(Charge$1.amount())).&&(Charge$1.canEqual(Charge.this))
    }));
    def <init>(cc: Int, amount: Double): Charge = {
      Charge.this.cc = cc;
      Charge.this.amount = amount;
      Charge.super.<init>();
      scala.Product$class./*Product$class*/$init$(Charge.this);
      ()
    }
  };
  <synthetic> object Charge extends scala.runtime.AbstractFunction2 with Serializable {
    final override <synthetic> def toString(): String = "Charge";
    case <synthetic> def apply(cc: Int, amount: Double): Charge = new Charge(cc, amount);
    case <synthetic> def unapply(x$0: Charge): Option = if (x$0.==(null))
      scala.this.None
    else
      new Some(new Tuple2$mcID$sp(x$0.cc(), x$0.amount()));
    <synthetic> private def readResolve(): Object = Charge;
    case <synthetic> <bridge> <artifact> def apply(v1: Object, v2: Object): Object = Charge.this.apply(scala.Int.unbox(v1), scala.Double.unbox(v2));
    def <init>(): Charge.type = {
      Charge.super.<init>();
      ()
    }
  }
}

which tells you that this.cc is provided from an actual property of the object via a method called cc().

Dr. Vick
  • 195
  • 2
  • 15