Thursday, July 25, 2013

Scala Traits decompilation and the rest: Scala version 2.10.2

package demo

trait Trait1 {
  def abstractMethod: Int
}
The above Scala Trait generates a Java Interface:

public interface demo.Trait1 {
  public abstract int abstractMethod();
}
Now let us find out what happens when a Scala Trait has got an implemented method along with an abstract one.
package demo

trait Trait3 {
  def abstractMethod: Int

  def implMethod: Int = 7
}
This one generates two Java entities:
public interface demo.Trait3 {
  public abstract int abstractMethod();

  public abstract int implMethod();
}

public abstract class demo.Trait3$class {
  public static int implMethod(demo.Trait3);
    Code:
       0: bipush        7
       2: ireturn      

  public static void $init$(demo.Trait3);
    Code:
       0: return       
}
So along with a sensible Java Interface, it also generated an abstract class with two static methods! Let us have a closer look at the first static method: it's name is same as the implemented method on the Trait and the default implementation logic is reflected too. But what's the use of this abstract class?

To understand how this abstract class is used let us use it, of course. :)

package demo

class SomeClass extends Trait3 {
  def abstractMethod = 1
}
And this is how it was used:
public class demo.SomeClass implements demo.Trait3 {
  public int implMethod();
    Code:
       0: aload_0      
       1: invokestatic  #17                 // Method demo/Trait3$class.implMethod:(Ldemo/Trait3;)I
       4: ireturn      

  public int abstractMethod();
    Code:
       0: iconst_1     
       1: ireturn      

  public demo.SomeClass();
    Code:
       0: aload_0      
       1: invokespecial #24                 // Method java/lang/Object."<init>":()V
       4: aload_0      
       5: invokestatic  #28                 // Method demo/Trait3$class.$init$:(Ldemo/Trait3;)V
       8: return       
}
 The SomeClass implements the generated Java Interface, demo.Trait3. makes sense.
But this class has also magically got the default implemented Scala Trait method, implMethod!
And how is this auto-generated method implemented? It simply delegates to the namesake static method in abstract class Trait3$class. No magic. Isn't it?

Wait a minute, if the generated Trait3$class has all static methods then what could have been the reason behind declaring it "abstract"? Please let me know when you find it. No, I am serious.

No comments: