jack
jack

Reputation: 357

Using Val in Scala Trait

I defined trait in Scala as

trait checkTrait
 {
     val name:String = "male"
 }

As i understand when val are declared in Scala Class only accessors are generated but when i decompiled above code using JAD decompiler following gets generated

public interface checkTrait
{

    public abstract void checkTrait$_setter_$name_$eq(String s);
    public abstract String name();
}

Not able to understand what exactly is "checkTrait$setter$name_$eq(String s)" is it Mutator? If it is Mutator then how they are getting generated, because as per language specification Mutators are not generated for Vals

Upvotes: 2

Views: 553

Answers (1)

chengpohi
chengpohi

Reputation: 14227

Yes, You are right. checkTrait$setter$name_$eq(String s) is a Mutator method for initing set name value.

This is caused of Scala trait will convert to Java interface, and Since Java interface fields is implicitly static and final, but in Scala trait field need to be an field of class or instance. so this Mutator method is used to init the field for checkTrait's subclass.

Java 8 (pre-release) interface member variables

Full Explanation:

As your decompilation, Scala Compiler convert trait checkTrait to Java's interface. and for this decompilation should have another static init method in checkTrait, like:

public interface checkTrait {
  public abstract void checkTrait$_setter_$name_$eq(java.lang.String);

  public abstract java.lang.String name();

  public static void $init$(checkTrait);
    Code:

       1: ldc           #18                 // String male
       3: invokeinterface #20,  2           // InterfaceMethod checkTrait$_setter_$name_$eq:(Ljava/lang/String;)V
       8: return
}

As you can see, this is a static init method with accepting a checkTrait instance parameter. and invoke checkTrait$_setter_$name_$eq this mutator method to initial set value with value: male.

Let us try to extend checkTrait:

class A extends checkTrait

and decompile this A class:

public class A implements checkTrait {
  public java.lang.String name();
    Code:
       0: aload_0
       1: getfield      #15                 // Field name:Ljava/lang/String;
       4: areturn

  public void checkTrait$_setter_$name_$eq(java.lang.String);
    Code:
       0: aload_0
       1: aload_1
       2: putfield      #15                 // Field name:Ljava/lang/String;
       5: return

  public A();
    Code:
       0: aload_0
       1: invokespecial #24                 // Method java/lang/Object."<init>":()V
       4: aload_0
       5: invokestatic  #28                 // InterfaceMethod checkTrait.$init$:(LcheckTrait;)V
       8: return
}

And we can find, In the A's constructor method, it will invoke the checkTrait static init method by:

5: invokestatic  #28                 // InterfaceMethod checkTrait.$init$:(LcheckTrait;)V

with pass current instance to init name field value.

So that's Scala way of implementing a field in trait.

Upvotes: 2

Related Questions