How to solve “Implementation restriction: trait … accesses protected method … inside a concrete trait method.”

只愿长相守 提交于 2019-12-05 07:50:12

The problem is that even though the trait extends the Java class, the implementation is not actually in something that extends the Java class. Consider

class A { def f = "foo" }
trait T extends A { def g = f + "bar" }
class B extends T { def h = g + "baz" }

In the actual bytecode for B we see

public java.lang.String g();
  Code:
   0:   aload_0
   1:   invokestatic    #17; //Method T$class.g:(LT;)Ljava/lang/String;
   4:   areturn

which means it just forwards to something called T$class, which it turns out is

public abstract class T$class extends java.lang.Object{
public static java.lang.String g(T);
  Code:
  ...

So the body of the code isn't called from a subclass of A at all.

Now, with Scala that's no problem because it just omits the protected flag from bytecode. But Java enforces that only subclasses can call protected methods.

And thus you have the problem, and the message.

You cannot easily get around this problem, though the error message suggests what is perhaps the best alternative:

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.

Note the last line.

class WithAccessor extends JavaProtected { protected def myAccessor = getInt }
trait T extends WithAccessor { def i = myAccessor }

works.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!