如何解决“实施限制:特征......访问受保护的方法......在具体的特征方法中。”

Posted

技术标签:

【中文标题】如何解决“实施限制:特征......访问受保护的方法......在具体的特征方法中。”【英文标题】:How to solve "Implementation restriction: trait ... accesses protected method ... inside a concrete trait method." 【发布时间】:2013-07-07 13:56:39 【问题描述】:

我正在使用的 Java 库类声明

protected getPage(): Page  ... 

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

实现限制:trait MyMixin 在具体的 trait 方法中访问受保护的方法 getPage

有没有办法让它工作而不影响我的子类?为什么会有这个限制?


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

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

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

【问题讨论】:

【参考方案1】:

问题在于,即使 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 

有效。

【讨论】:

谢谢,这是我想避免的,将访问器添加到我的子类中。但现在我明白为什么不可能了。 @PetrPudlák - 您不必将访问器添加到 每个 子类,只需添加到 一个 启用访问器的原始子类。然后,所有其他混入特征的类将扩展访问器启用类而不是原始类。 (当然,受保护的访问器将成为接口的一部分,但至少您只需编写一次。) 问题是我想将 trait 混合到 Java 类中,其唯一的公共超类在 Java 库中。这就是为什么我想使用 mixin trait 来添加功能,而不必为我扩展的每个 Java 类创建一个 Scala 子类。 @PetrPudlák - 啊。好吧,反射(在没有限制性安全管理器的环境中)将允许它。选择方法,调用.setAccessible(true)invoke 它,转换为正确的类型。我根本不推荐这个。

以上是关于如何解决“实施限制:特征......访问受保护的方法......在具体的特征方法中。”的主要内容,如果未能解决你的问题,请参考以下文章

如何解决包冲突问题

如何解决包冲突问题

如何解决ajax跨域问题

MySQL 的 10048问题,如何解决?

如何解决smartgit的冲突问题

如何解决https传输图片的问题