如何解决“实施限制:trait ...访问受保护的方法...在具体trait方法内部”。 [英] How to solve "Implementation restriction: trait ... accesses protected method ... inside a concrete trait method."

查看:273
本文介绍了如何解决“实施限制:trait ...访问受保护的方法...在具体trait方法内部”。的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

一个Java库类我使用声明

A Java library class I'm using declares

protected getPage(): Page { ... }



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

Now I want to make a helper Scala mixin to add features that I often use. I don't want to extend the class, because the Java class has different subclasses I want to extend at different places. The problem is that if I use getPage() in my mixin trait, I get this error:


实施限制:trait MyMixin 访问受保护的方法 getPage in a concrete trait method。

Implementation restriction: trait MyMixin accesses protected method getPage inside a concrete trait method.

有没有解决方案如何使它工作, 为什么会有这个限制?

Is there a solution how to make it work, without affecting my subclasses? And why is there this restriction?

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

So far, I came up with a work-around: I override the method in the trait as

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

这似乎工作,但我不完全满意。幸运的是,我不需要重写 getPage()在我的子类,但如果我需要,我会得到两个重写相同的方法, t工作。

This seems to work, but I'm not completely satisfied. Luckily I don't need to override getPage() in my subclasses, but if I needed, I'd get two overrides of the same method and this work-around won't work.

推荐答案

问题是,即使trait扩展了Java类,实现实际上不是扩展Java类。考虑

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" }

B 的实际字节码中,我们看到

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

这意味着它只是转发到 T $ class ,结果是

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:
  ...

现在,使用Scala没有问题,因为它只是忽略了一个子类的 A protected 从字节码标志。但 Java 强制只有子类可以调用受保护的方法。

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.

注意最后一行。

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

工程。

这篇关于如何解决“实施限制:trait ...访问受保护的方法...在具体trait方法内部”。的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆