问题是即使 trait 扩展了 Java 类,实现实际上并不是在扩展 Java 类的东西中。考虑
class A { def f = "foo" }
trait T extends A { def g = f + "bar" }
class B extends T { def h = g + "baz" }
在B
我们看到的实际字节码中
public java.lang.String g();
Code:
0: aload_0
1: invokestatic #17; //Method T$class.g:(LT;)Ljava/lang/String;
4: areturn
这意味着它只是转发到一个叫做 的东西T$class
,结果是
public abstract class T$class extends java.lang.Object{
public static java.lang.String g(T);
Code:
...
所以代码的主体根本不是从子类调用的A
。
现在,使用 Scala 没问题,因为它只是protected
从字节码中省略了标志。但是Java
强制只有子类可以调用受保护的方法。
因此,您遇到了问题和信息。
您无法轻松解决此问题,尽管错误消息表明什么可能是最好的选择:
public class JavaProtected {
protected int getInt() { return 5; }
}
scala> trait T extends JavaProtected { def i = getInt }
<console>:8: error: Implementation restriction: trait T accesses
protected method getInt inside a concrete trait method.
Add an accessor in a class extending class JavaProtected as a workaround.
注意最后一行。
class WithAccessor extends JavaProtected { protected def myAccessor = getInt }
trait T extends WithAccessor { def i = myAccessor }
作品。