由于特征不仅仅是接口,它们需要某种方式来存储它们的内部状态。但是它们必须与接口兼容——那么它们是做什么的呢?他们为看起来像一个字段的内容创建访问器(如您javap -l -s -c -private
在类文件中看到的(除其他外)):
public interface T1 extends java.lang.Object {
public abstract int T1$$v();
Signature: ()I
public abstract int getValueT1();
Signature: ()I
}
然后创建一个具有静态方法来实现功能的实现类:
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; //InterfaceMethod T1.T1$$v:()I
6: ireturn
}
现在,希望很明显,默认情况下它们是分开的,因为这些内部生成的方法在方法名称中具有特征名称。当我们查看实现时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 #22; //Field T1$$v:I
4: ireturn
public int getValueT1();
Signature: ()I
Code:
0: aload_0
1: invokestatic #29; //Method T1$class.getValueT1:(LT1;)I
4: ireturn
}
您可以看到它只是填充了每个特定特征所需的内容。现在的问题是——特征如何相互覆盖?他们似乎完全分开了!那是编译器的工作。如果某些东西是private
隐藏的并且不能被覆盖,那么另一个(私有)事物具有相同的名称并不重要。但如果不是,编译器会抱怨冲突:
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
因为现在它没有使用嵌入特征名称的秘密重整名称。(请注意,getValueT1
在此示例中未损坏。)