Since traits are not just interfaces, they need some kind of storage for their internal state. But they must be compatible with the interfaces - so what do they do? They create accessors for what looks like a field (as you can see (among other things) with javap -l -s -c -private in class files):
public interface T1 extends java.lang.Object { public abstract int T1$$v(); Signature: ()I public abstract int getValueT1(); Signature: ()I }
and then create an implementation class that has static methods for implementing the functionality:
public abstract class T1$class extends java.lang.Object { public static int getValueT1(T1); Signature: (LT1;)I Code: 0: aload_0 1: invokeinterface #12, 1;
Now, hopefully, itβs clear that they will be separate by default, because these built-in methods have a tag name in the method name. And when we look at the implementation in T12 :
public class T12 extends java.lang.Object implements T1,T2,scala.ScalaObject { private final int Overridden$T1$$v; Signature: I public final int T1$$v(); Signature: ()I Code: 0: aload_0 1: getfield
you can see that it simply fills in what is needed for each particular attribute. Now the question is: how do features ever rewrite each other? They seem completely separate! This is the work of the compiler. If something is private , it is hidden and cannot be redefined, so it does not matter that another (private) thing has the same name. But if it is not, the compiler complains about a collision:
error: overriding value v in trait T1 of type Int; value v in trait T2 of type Int needs `override' modifier class T12 extends T1 with T2
because now it doesnβt use secret misrepresented names with an embedded feature name. (Note that getValueT1 not distorted in this example.)
Rex kerr
source share