请看以下代码段:
class C
val c1 = new C { def m1 = "c1 has m1" }
val c2 = new C { def m2 = "c2 has m2" }
c1.m1
c2.m2
//c2.m1
//c1.m2
在REPL中运行它,那么您知道我的意思了。
我有限的Java知识告诉我,在Java中,相同类的对象将具有相同的方法签名,就OO而言,Java与底层Scala之间没有太大区别。 (如果我错了,请纠正我),因此我很惊讶地看到该片段是声音scala代码。
那为什么呢?
您要用特征扩展C
,所以c1
和c2
是匿名类:
scala> c1.getClass
res0: java.lang.Class[_ <: C] = class $anon$1
scala> c2.getClass
res1: java.lang.Class[_ <: C] = class $anon$2
查看Java代码,您会看到(O
是一个周围的对象,可以对其进行编译):
public final class O$$anon$1 extends O$C {
public java.lang.String m1();
public O$$anon$1();
}
public final class O$$anon$2 extends O$C {
public java.lang.String m2();
public O$$anon$2();
}
Java等价于
C c1 = new C {
public String m1() { ... }
}
C c2 = new C {
public String m2() { ... }
}
现在,您不能直接调用c1.m1()
,但可以使用反射来进行操作:
c1.getClass().getMethod("m1").invoke(c1)
Scala仅允许您使用更简单的语法来完成它。