6

我正在使用的 Java 库类声明

protected getPage(): Page { ... }

现在我想制作一个辅助 Scala mixin 来添加我经常使用的功能。我不想扩展类,因为Java类有不同的子类我想在不同的地方扩展。问题是,如果我getPage()在我的 mixin中使用trait,我会收到此错误:

实现限制:特征MyMixin访问getPage具体特征方法内的受保护方法。

有没有解决方案如何使它工作,而不影响我的子类?为什么会有这个限制?


到目前为止,我想出了一个解决方法:我将 trait 中的方法重写为

override def getPage(): Page = super.getPage();

这似乎有效,但我并不完全满意。幸运的是,我不需要getPage()在我的子类中重写,但如果我需要,我会获得相同方法的两个重写,而这种解决方法将不起作用。

4

1 回答 1

10

问题是即使 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 }

作品。

于 2013-07-09T20:19:11.643 回答