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.
Related
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))
}
Trying to get values of all fields of child from parent class like this:
for (field <- this.getClass.getDeclaredFields) {
Logger.debug(field.getName)
field.get(this)
}
and got error
Exception: Class models.Model$$anonfun$4 can not access a member of
class models.Good with modifiers "private"
at line
field.get(this)
In Good class I don't have private fields:
class Good(id: Option[String]) extends Model[realGood](id){
lazy val title: String = this.load[String](realObject.get.title)
lazy val cost: Double = this.load[Double](realObject.get.cost)
}
What's wrong with this code?
As hinted in the comments, Scala's conversion to java bytecode isn't always straightforward (though it's usually pretty predictable, once you get the hang of it). In particular, public fields in Scala compile to a private field with a public getter in java bytecode:
fukaeri:~ dlwh$ cat zzz.scala
class Good(id: Option[String]) {
lazy val title: String = ???
lazy val cost: Double = ???
}
fukaeri:~ dlwh$ scalac zzz.scala
fukaeri:~ dlwh$ javap -private Good
Compiled from "zzz.scala"
public class Good {
private java.lang.String title;
private double cost;
private volatile byte bitmap$0;
private java.lang.String title$lzycompute();
private double cost$lzycompute();
public java.lang.String title();
public double cost();
public Good(scala.Option<java.lang.String>);
}
You can see that Good has private fields for each of your declared public fields, in addition to public getters. Because the fields are lazy val, they also have computation methods for initialization, and there's a bitmap$0 field to ensure that the lazy vals are initialized only once.
In your loop, you can use field.setAccessible(true) to fix your exception.
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.
I'm trying to understand implementation of object-private variables in Scala. Scala compiles this class
class Counter{
private[this] var age = 0
}
into the following java byte code:
public class Counter implements scala.ScalaObject {
private int age;
public Counter();
}
But still, because JVM doesn't support object-private fields, we have good-old private field, which can be accessed from other instances of the class. So for me the difference between previous class and the following in terms of hiding private field is not clear.
class Counter2{
private var age = 0
}
public class Counter2 implements scala.ScalaObject {
private int age;
private int age();
private void age_$eq(int);
public Counter2();
}
The JVM is irrelevant. The semantics of Scala are implemented by the Scala compiler, not the JVM. After all, the JVM isn't even the only platform Scala runs on, there are production-ready implementations of Scala on the CLI, and experimental ones on ECMAScript as well as a native one.
I created a hierarchy of case objects in Scala that looks like the following:
package my.awesome.package
sealed abstract class PresetShapeType(val displayName: String)
case object AccelerationSensor extends PresetShapeType("Acceleration Sensor")
case object DisplacementSensor extends PresetShapeType("Displacement Sensor")
case object ForceSensor extends PresetShapeType("Force Sensor")
case object PressureSensor extends PresetShapeType("Pressure Sensor")
case object StrainSensor extends PresetShapeType("Strain Sensor")
I also have a piece of Java code in which I'd like to access PressureSensor, but the following does not work:
package my.awesome.package.subpackage;
import my.awesome.package.PressureSensor;
// Do some stuff, then...
DVShape newshape = DVShapeFactory.createPresetShape(PressureSensor, new Point3f(0,0,0));
So, how do I reference the PressureSensor case object from Java? I decompiled the byte code for both the PressureSensor and PressureSensor$ classes, which yielded the following:
Compiled from "DVShapeFactory.scala"
public final class org.nees.rpi.vis.PressureSensor extends java.lang.Object{
public static final java.lang.Object productElement(int);
public static final int productArity();
public static final java.lang.String productPrefix();
public static final int $tag();
public static final java.lang.String displayName();
}
Compiled from "DVShapeFactory.scala"
public final class org.nees.rpi.vis.PressureSensor$ extends org.nees.rpi.vis.PresetShapeType implements scala.ScalaObject,scala.Product,java.io.Serializable{
public static final org.nees.rpi.vis.PressureSensor$ MODULE$;
public static {};
public org.nees.rpi.vis.PressureSensor$();
public java.lang.Object readResolve();
public java.lang.Object productElement(int);
public int productArity();
public java.lang.String productPrefix();
public final java.lang.String toString();
public int $tag();
}
But that didn't yield any great insight.
from Java, say:
my.awesome.package.PressureSensor$.MODULE$
PressureSensor$.MODULE$ should give you the instance of the case object.
This is still a hack, but in my opinion a bit more readable in Java. Just add a method to explicitly return the reference to the singleton instance (it shows up as a static method on the class):
sealed abstract class PresetShapeType(val displayName: String)
case object AccelerationSensor extends PresetShapeType("Acceleration Sensor") { def instance = this }
case object DisplacementSensor extends PresetShapeType("Displacement Sensor") { def instance = this }
case object ForceSensor extends PresetShapeType("Force Sensor") { def instance = this }
case object PressureSensor extends PresetShapeType("Pressure Sensor") { def instance = this }
case object StrainSensor extends PresetShapeType("Strain Sensor") { def instance = this }
And then in Java:
import my.awesome.package.PressureSensor;
DVShape newshape = DVShapeFactory.createPresetShape(PressureSensor.instance(), new Point3f(0,0,0));