Understanding Case class and Traits in Scala - scala

I have a simple trait as defined below:
trait MyTrait {
def myStringVal: String
}
My case class which implements this trait is as below:
case class MyCaseClass(myStringVal: String) extends MyTrait {
...
...
}
Coming from a Java world, I find it a bit difficult to fathom the fact that MyCaseClass actually implements this just by defining a parameter to MyCaseClass. I understand that thy byte code would actually write the getter and setter. But how is this possible without any var or val?
My understanding is that if there is no var or val, then there is no getter or setter method generated. In that case how is the above case class MyCaseClass implementing myStringVal method?
Sometime too much of this Scala magic is difficult to understand especially with legacy code.

You might want to check out this blog article covering what case classes exactly are and why they are so useful.
In your example, the trait MyTrait has no use, except being able to function like a java interface. Note, that the default visibility in scala is public. By default case class parameters are immutable so in your example val is automatically inferred by the compiler for the myStringVal argument.
What magic do case classes do?!
Convert all constructor parameters to public readonly (val) by default fields
Generate the toString(), equals() and hashcode() methods using all constructor params for each method
Generate companion object with the same name containing an appropriate apply() and unapply() method, which are basically just a convenience constructor allowing to instantiate without using the new keyword and an extractor which by default generates an option-wrapped tuple of the case class parameters.
EDIT: Sample compiler output for (case) classes (copied from scalatutorial.de)
A simple scala class definition like
class A1(v1: Int, v2: Double)
gets compiled to the java code
public class A1 extends java.lang.Object implements scala.ScalaObject {
public A1(int, double);
}
the analogous case class
case class A2(v1: Int, v2: Double)
gets compiled to the following java classes
public class A2 extends java.lang.Object implements
scala.ScalaObject,scala.Product,java.io.Serializable {
public static final scala.Function1 tupled();
public static final scala.Function1 curry();
public static final scala.Function1 curried();
public scala.collection.Iterator productIterator();
public scala.collection.Iterator productElements();
public double copy$default$2();
public int copy$default$1();
public int v1();
public double v2();
public A2 copy(int, double);
public int hashCode();
public java.lang.String toString();
public boolean equals(java.lang.Object);
public java.lang.String productPrefix();
public int productArity();
public java.lang.Object productElement(int);
public boolean canEqual(java.lang.Object);
public A2(int, double);
}
public final class A2$ extends scala.runtime.AbstractFunction2
implements scala.ScalaObject {
public static final A2$ MODULE$;
public static {};
public scala.Option unapply(A2);
public A2 apply(int, double);
public java.lang.Object apply(java.lang.Object, java.lang.Object);
}

Scala case classes have a plenty of boilerplate implemented for you, and having all the constructor parameters automatically exposed as vals is one of these things.
If you try avoiding vals in a regular class, like that:
trait MyTrait {
def myVal: String
}
class MyClass(myVal: String) extends MyTrait
Compiler will show you the error message, that MyClass has to be abstract, as it does't override myVal method, but adding val or var to the class constructor parameter will solve the issue.

Case classes are different -- some default methods are generated for them. This includes val getters for the parameters. Think of case classes as POJOs -- this is a useful bit of syntactic sugar, since they don't need private members.
Some other useful methods are generated too, for example copy, toString, apply and unapply.

Related

How to implement a Java abstract interface in Scala

How do you implement a Java abstract interface in scala?
Abstract interface :
public abstract interface KeyIndex<K>
extends Serializable
{
public abstract long toIndex(K paramK);
public abstract Seq<Tuple2<Object, Object>> indexRanges(Tuple2<K, K> paramTuple2);
}
It seems, that your KeyIndex class is written in Java. In Scala every field not labeled private or protected is public. There is no public keyword in Scala.
But implementing a Java class in Scala is possible:
class KeyIndexImpl extends KeyIndex[geotrellis.spark.SpatialKey]{
override def toIndex(paramK: geotrellis.spark.SpatialKey): Long =
1l
override def indexRanges(paramTuple2: (geotrellis.spark.SpatialKey, geotrellis.spark.SpatialKey)): Seq[(AnyRef, AnyRef)] =
Seq((paramTuple2, paramTuple2))
}

Merging of custom and compiler generated companion objects for a case class. What are the merging rules?

I just tried out this code below and it worked as expected. It prints 1.
Now, my problem is that I don't understand what is going on under the hood.
How can a case class have two companion objects (One generated by the compiler and one written by me) ? Probably it cannot. So they must be merged somehow under the hood. I just don't understand how are they merged ? Are there any special merging rules I should be aware of ?
Is it so that, if the set of definitions defined in both companion objects are disjoint then the set of definitions in the resulting case class is simply the union of two disjoint sets ? I would think this is how they are merged, but I am not sure. Can someone please confirm whether this merging rule is the one that is implemented in the Scala compiler? Or is there something extra to it ?
More specifically, what are the rules by which the compiler generated companion object and my companion object are merged ? Are these rules specified somewhere ?
I have not really seen this topic discussed in the few Scala books I have - perhaps too superficially - read.
object A{
implicit def A2Int(a:A)=a.i1
}
case class A(i1:Int,i2:Int)
object Run extends App{
val a=A(1,2)
val i:Int=a
println(i)
}
I'm not aware of where the algorithm for merging automatic and explicit companion objects is described or documented (other than the compiler source) but by compiling your code and then examining the generated companion object (using javap), we can see what the differences are (this is with scala 2.10.4).
Here's the companion object generated for the case class (without your additional companion object):
Compiled from "zip.sc"
public final class A$ extends scala.runtime.AbstractFunction2<Object, Object, A> implements scala.Serializable {
public static final A$ MODULE$;
public static {};
public A apply(int, int);
public scala.Option<scala.Tuple2<java.lang.Object, java.lang.Object>> unapply(A);
public java.lang.Object apply(java.lang.Object, java.lang.Object);
public final java.lang.String toString();
}
After adding your companion object, here's what is generated:
Compiled from "zip.sc"
public final class A$ implements scala.Serializable {
public static final A$ MODULE$;
public static {};
public A apply(int, int);
public scala.Option<scala.Tuple2<java.lang.Object, java.lang.Object>> unapply(A);
public int A2Int(A);
}
The differences in the generated companion object caused by the explicit companion object definition appear to be:
it no longer extends AbstractFunction2
it no longer has the factory method (apply) related to bullet 1
it no longer overrides the toString method (I suppose you are expected to supply one, if needed)
your A2Int method is added
If the case class is changed to an ordinary class (along with minimal changes required to get it to compile), the result is the following:
Compiled from "zip.sc"
public final class A$ {
public static final A$ MODULE$;
public static {};
public A apply(int, int);
public int A2Int(A);
}
So it seems that if you declare your own companion object, at least in this simple example, the effect is that your new method is added to the companion object, and some of it's implementation and functionality are lost as well. It would be interesting to see what would happen if we tried to override some of the remaining auto-generated stuff, but there's not much left, so that in general is unlikely to cause conflict.
Some of the benefits of case classes are unrelated to the generated code, such as making the class variables public without having to explicitly add the 'val' keyword. Here's the modified source code for all 3 decompiled examples above.
version 1 (no explicit companion object):
case class A(i1:Int,i2:Int)
version 2 is your original version.
version 3 (no case-class):
object A {
implicit def A2Int(a:A)=a.i1
def apply(a:Int,b:Int):A = new A(a,b)
}
class A(val i1:Int,val i2:Int)
object Run extends App{
import A._
val a=A(1,2)
val i:Int=a
}
In version 3, we need to add val to class A parameters (otherwise they're private), and we have to either add the factory method to our companion object, or use the 'new' keyword when creating an instance of A(1,2).

In Scala, is it possible to have a case class containing methods with identical names to fields?

I think I'd like to be able to do something like the following (clearly garbage) code illustrates:
// Clearly nonsensical
case class Example(a: String) {
def a: Array[Byte] = a.getBytes
}
The gist of it is that I want to write an accessor method for a case class that is named identically to one of its constructor arguments.
I'm using a JSON serialization library called Jerkson that, according to my understanding, will behave in the way I want it to if I define a class in this manner. I'm basing that assumption on this code. Currently, I'm stumped.
If this isn't possible, could anyone offer some insight on what the Jerkson library code is attempting to do?
Scala automatically creates a method with the same name as any val declared in a class (including the fields of case classes) to support a concept called referential transparency. This is also why you can override a def with a val. If you're still skeptical, you can test it yourself like this:
First, create a Scala file with a single case class.
// MyCase.scala
case class MyCase(myField1: Int, myField2: String)
Now, compile the file with scalac. This should result in two classes. For the example above I get MyCase.class (representing the actual case class type) and MyCase$.class (representing the auto-generated companion object for the case class).
$ scalac MyCase.scala
$ ls
MyCase$.class MyCase.class MyCase.scala
Now you can examine the resulting .class file corresponding to the case class you declared using javap. (javap standard tool for examining Java bytecode—it's distributed along with javac in the JDK.)
$ javap -private MyCase
Compiled from "MyCase.scala"
public class MyCase extends java.lang.Object implements scala.Product,scala.Serializable{
private final int myField1;
private final java.lang.String myField2;
public static final scala.Function1 tupled();
public static final scala.Function1 curry();
public static final scala.Function1 curried();
public scala.collection.Iterator productIterator();
public scala.collection.Iterator productElements();
public int myField1();
public java.lang.String myField2();
public MyCase copy(int, java.lang.String);
public java.lang.String copy$default$2();
public int copy$default$1();
public int hashCode();
public java.lang.String toString();
public boolean equals(java.lang.Object);
public java.lang.String productPrefix();
public int productArity();
public java.lang.Object productElement(int);
public boolean canEqual(java.lang.Object);
private final boolean gd1$1(int, java.lang.String);
public MyCase(int, java.lang.String);
}
Notice how the resulting class has both a private final int myField1 and a public int myField1() corresponding to the case class's myField1 field. The same for myField2.
On the JVM method return types are not part of the method signature. This means that if two methods have the same name and the same argument types then they're considered to be conflicting method declarations. This means you can't declare the def a: Array[Byte] in your example because val a: String already exists, also taking no arguments.
Update:
I just looked at the library code and according to the examples the case classes should just work. There is a note in the README saying that parsing case classes does not work in the REPL. Could that be your problem? If not, you should really post the error you're getting. Edit: Never mind, I see the error you're talking about in your link to your other post. If I think of a response to that problem I'll post it over there.
No, it's not possible. The reason is that constructor arguments of case classes are automatically public values, like if you declare them with val. To quote A Tour of Scala: Case Classes
The constructor parameters of case classes are treated as public values and can be accessed directly.
Therefore, for each constructor argument Scala creates a corresponding accessor method with the same name. You cannot create a method with the same name, it's already there.
This is actually what case classes are about. The idea is that they can be used for pattern matching, so the values retrieved from them should be the same as the values used to construct them.
(Is it a requirement that you use case classes? Using regular classes seems to solve the problem.)

Scala object MODULE$

What's the purpose of Scala object MODULE$?
The following Scala object:
object TestScalaObject {
val TEST_SYMBOL = "*"
def testMethod(x : String) : String = x
}
compiles into two bytecode files TestScalaObject.class and TestScalaObject$.class which if I disassemble to get the equivalent Java code I get:
TestScalaObject.class:
public final class TestScalaObject extends java.lang.Object{
public static final java.lang.String testMethod(java.lang.String);
public static final java.lang.String TEST_SYMBOL();
}
TestScalaObject$.class:
public final class TestScalaObject$ extends java.lang.Object implements scala.ScalaObject{
public static final TestScalaObject$ MODULE$;
public static {};
public java.lang.String TEST_SYMBOL();
public java.lang.String testMethod(java.lang.String);
}
I can see a public static final TestScalaObject$.MODULE$ but what is it used for if I can access everything I need through TestScalaObject.TEST_SYMBOL and TestScalaObject.testMethod() if I ever wanted to do that from Java
MODULE$ holds an instance of the instantiated class. See the Singleton pattern in Java. I don't know of a good source for it, so here's the Wikipedia entry for Singleton.

Difference between case object and object

Is there any difference between case object and object in scala?
Here's one difference - case objects extend the Serializable trait, so they can be serialized. Regular objects cannot by default:
scala> object A
defined module A
scala> case object B
defined module B
scala> import java.io._
import java.io._
scala> val bos = new ByteArrayOutputStream
bos: java.io.ByteArrayOutputStream =
scala> val oos = new ObjectOutputStream(bos)
oos: java.io.ObjectOutputStream = java.io.ObjectOutputStream#e7da60
scala> oos.writeObject(B)
scala> oos.writeObject(A)
java.io.NotSerializableException: A$
Case classes differ from regular classes in that they get:
pattern matching support
default implementations of equals and hashCode
default implementations of serialization
a prettier default implementation of toString, and
the small amount of functionality that they get from automatically inheriting from scala.Product.
Pattern matching, equals and hashCode don't matter much for singletons (unless you do something really degenerate), so you're pretty much just getting serialization, a nice toString, and some methods you probably won't ever use.
scala> object foo
defined object foo
scala> case object foocase
defined object foocase
Serialization difference:
scala> foo.asInstanceOf[Serializable]
java.lang.ClassCastException: foo$ cannot be cast to scala.Serializable
... 43 elided
scala> foocase.asInstanceOf[Serializable]
res1: Serializable = foocase
toString difference:
scala> foo
res2: foo.type = foo$#7bf0bac8
scala> foocase
res3: foocase.type = foocase
A huge necro, but it is the highest result for this question in Google outside official tutorial which, as always, is pretty vague about the details. Here are some bare bones objects:
object StandardObject
object SerializableObject extends Serializable
case object CaseObject
Now, lets use the very useful feature of IntelliJ 'decompile Scala to Java' on compiled .class files:
//decompiled from StandardObject$.class
public final class StandardObject$ {
public static final StandardObject$ MODULE$ = new StandardObject$();
private StandardObject$() {
}
}
//decompiled from StandardObject.class
import scala.reflect.ScalaSignature;
#ScalaSignature(<byte array string elided>)
public final class StandardObject {
}
As you can see, a pretty straightforward singleton pattern, except for reasons outside the scope of this question, two classes are generated: the static StandardObject (which would contain static forwarder methods should the object define any) and the actual singleton instance StandardObject$, where all methods defined in the code end up as instance methods. Things get more intresting when you implement Serializable:
//decompiled from SerializableObject.class
import scala.reflect.ScalaSignature;
#ScalaSignature(<byte array string elided>)
public final class SerializableObject {
}
//decompiled from SerializableObject$.class
import java.io.Serializable;
import scala.runtime.ModuleSerializationProxy;
public final class SerializableObject$ implements Serializable {
public static final SerializableObject$ MODULE$ = new SerializableObject$();
private Object writeReplace() {
return new ModuleSerializationProxy(SerializableObject$.class);
}
private SerializableObject$() {
}
}
The compiler doesn't limit itself to simply making the 'instance' (non-static) class Serializable, it adds a writeReplace method. writeReplace is an alternative to writeObject/readObject; what it does, it serializes a different object whenether the Serializable class having this method is being serialized. On deserializention then, that proxy object's readResolve method is invoked once it is deserialized. Here, a ModuleSerializableProxy instance is serialized with a field carrying the Class[SerializableObject], so it knows what object needs to be resolved. The readResolve method of that class simply returns SerializableObject - as it is a singleton with a parameterless constructor, scala object is always structurally equal to itself between diffrent VM instances and different runs and, in this way, the property that only a single instance of that class is created per one VM instance is preserved. A thing of note is that there is a security hole here: no readObject method is added to SerializableObject$, meaning an attacker can maliciously prepare a binary file which matches standard Java serialization format for SerializableObject$ and a separate instance of the 'singleton' will be created.
Now, lets move to the case object:
//decompiled from CaseObject.class
import scala.collection.Iterator;
import scala.reflect.ScalaSignature;
#ScalaSignature(<byte array string elided>)
public final class CaseObject {
public static String toString() {
return CaseObject$.MODULE$.toString();
}
public static int hashCode() {
return CaseObject$.MODULE$.hashCode();
}
public static boolean canEqual(final Object x$1) {
return CaseObject$.MODULE$.canEqual(var0);
}
public static Iterator productIterator() {
return CaseObject$.MODULE$.productIterator();
}
public static Object productElement(final int x$1) {
return CaseObject$.MODULE$.productElement(var0);
}
public static int productArity() {
return CaseObject$.MODULE$.productArity();
}
public static String productPrefix() {
return CaseObject$.MODULE$.productPrefix();
}
public static Iterator productElementNames() {
return CaseObject$.MODULE$.productElementNames();
}
public static String productElementName(final int n) {
return CaseObject$.MODULE$.productElementName(var0);
}
}
//decompiled from CaseObject$.class
import java.io.Serializable;
import scala.Product;
import scala.collection.Iterator;
import scala.runtime.ModuleSerializationProxy;
import scala.runtime.Statics;
import scala.runtime.ScalaRunTime.;
public final class CaseObject$ implements Product, Serializable {
public static final CaseObject$ MODULE$ = new CaseObject$();
static {
Product.$init$(MODULE$);
}
public String productElementName(final int n) {
return Product.productElementName$(this, n);
}
public Iterator productElementNames() {
return Product.productElementNames$(this);
}
public String productPrefix() {
return "CaseObject";
}
public int productArity() {
return 0;
}
public Object productElement(final int x$1) {
Object var2 = Statics.ioobe(x$1);
return var2;
}
public Iterator productIterator() {
return .MODULE$.typedProductIterator(this);
}
public boolean canEqual(final Object x$1) {
return x$1 instanceof CaseObject$;
}
public int hashCode() {
return 847823535;
}
public String toString() {
return "CaseObject";
}
private Object writeReplace() {
return new ModuleSerializationProxy(CaseObject$.class);
}
private CaseObject$() {
}
}
A lot more is going on, as CaseObject$ now implements also Product0, with its iterator and accessor methods. I am unaware of a use case for this feature, it is probably done for consistency with case class which is always a product of its fields. The main practical difference here is that we get canEqual, hashCode and toString methods for free. canEqual is relevant only if you decide to compare it with a Product0 instance which is not a singleton object, toString saves us from implementing a single simple method, which is useful when case objects are used as enumeration constants without any behaviour implemented. Finally, as one might suspect, hashCode returns a constant, so it is the same for all VM instances. This matters if one serializes some flawed hash map implementation, but both standard java and scala hash maps wisely rehash all contents on deserialization, so it shouldn't matter. Note that equals is not overriden, so it is still reference equality, and that the security hole is still there. A huge caveat here: if a case object inherit equals/toString from some supertype other than Object, the corresponding methods are not generated, and the inherited definitions are used instead.
TL;DR: the only difference that matters in practice is the toString returning the unqualified name of the object.
I must make a disclamer here, though: I cannot guarantee that the compiler doesn't treat case objects specially in addition to what is actually in the bytecode. It certainly does so when patterm matching case classes, aside from them implementing unapply.
It's similar with case class and class ,we just use case object instead of case class when there isn't any fields representing additional state information.
case objects implicitly come with implementations of methods toString, equals, and hashCode, but simple objects don't.
case objects can be serialized while simple objects cannot, which makes case objects very useful as messages with Akka-Remote.
Adding the case keyword before object keyword makes the object serializable.
We know objects and "case class" before. But "case object" is a mix of both i.e it is a singleton similar to an object and with a lot of boilerplate as in a case class. The only difference is that the boilerplate is done for an object instead of a class.
case objects won't come with the below ones:
Apply, Un-apply methods.
here are no copy methods since this is a singleton.
No method for structural equality comparison.
No constructor as well.