答
从Java的角度被编译成接口。因此,在Java中实现被解释为实现接口 - 这使您的错误消息显而易见。简短的回答:你不能利用Java中的特征实现,因为这会在Java中实现多重继承(!)Trait.scala
Trait
Trait
它是如何在Scala中实现的?
长答案:那么它在Scala中是如何工作的呢?查看生成的字节码/类,可以找到以下代码:
interface Trait {
void bar();
}
abstract class Trait$class {
public static void bar(Trait thiz) {/*trait implementation*/}
}
class Foo implements Trait {
public void bar() {
Trait$class.bar(this); //works because `this` implements Trait
}
}
-
Trait
是一个接口
- 抽象(不要与)类是透明创建的,从技术上讲,它不实现接口。但是,它确实有一个将实例作为参数的方法(某种程度上
Trait$class
Trait.class
Trait
static bar()
Trait
this
)
-
Foo
实现接口Trait
-
scalac
通过委派 给 自动实现方法。这实质上意味着调用 .Trait
Trait$class
Trait$class.bar(this)
请注意,既不是 的成员,也不是 扩展它的成员。它只是通过传递来委派给它。Trait$class
Foo
Foo
this
混合多种性状
继续关于Scala如何工作的题外话...话虽如此,很容易想象混合多种特征在下面是如何工作的:
trait Trait1 {def ping(){}};
trait Trait2 {def pong(){}};
class Foo extends Trait1 with Trait2
翻译为:
class Foo implements Trait1, Trait2 {
public void ping() {
Trait1$class.ping(this); //works because `this` implements Trait1
}
public void pong() {
Trait2$class.pong(this); //works because `this` implements Trait2
}
}
覆盖同一方法的多个特征
现在很容易想象混合多个特征如何覆盖相同的方法:
trait Trait {def bar(){}};
trait Trait1 extends Trait {override def bar(){}};
trait Trait2 extends Trait {override def bar(){}};
再次并将成为扩展的接口。现在,如果最后定义:Trait1
Trait2
Trait
Trait2
Foo
class Foo extends Trait1 with Trait2
您将获得:
class Foo implements Trait1, Trait2 {
public void bar() {
Trait2$class.bar(this); //works because `this` implements Trait2
}
}
但是,切换和(最后)将导致:Trait1
Trait2
Trait1
class Foo implements Trait2, Trait1 {
public void bar() {
Trait1$class.bar(this); //works because `this` implements Trait1
}
}
可堆叠修改
现在考虑一下作为可堆叠修改的特征是如何工作的。想象一下,有一个非常有用的类Foo:
class Foo {
def bar = "Foo"
}
您希望使用特征通过一些新功能来丰富它:
trait Trait1 extends Foo {
abstract override def bar = super.bar + ", Trait1"
}
trait Trait2 extends Foo {
abstract override def bar = super.bar + ", Trait2"
}
这是类固醇上的新“Foo”:
class FooOnSteroids extends Foo with Trait1 with Trait2
它翻译为:
特质1
interface Trait1 {
String Trait1$$super$bar();
String bar();
}
abstract class Trait1$class {
public static String bar(Trait1 thiz) {
// interface call Trait1$$super$bar() is possible
// since FooOnSteroids implements Trait1 (see below)
return thiz.Trait1$$super$bar() + ", Trait1";
}
}
特质2
public interface Trait2 {
String Trait2$$super$bar();
String bar();
}
public abstract class Trait2$class {
public static String bar(Trait2 thiz) {
// interface call Trait2$$super$bar() is possible
// since FooOnSteroids implements Trait2 (see below)
return thiz.Trait2$$super$bar() + ", Trait2";
}
}
FooOnSteroids
class FooOnSteroids extends Foo implements Trait1, Trait2 {
public final String Trait1$$super$bar() {
// call superclass 'bar' method version
return Foo.bar();
}
public final String Trait2$$super$bar() {
return Trait1$class.bar(this);
}
public String bar() {
return Trait2$class.bar(this);
}
}
因此,整个堆栈调用如下所示:
- FooOnSteroids实例上的'bar'方法(入口点);
- Trait2$class 的 'bar' 静态方法将此作为参数传递,并返回 'Trait2$$super$bar()' 方法调用和字符串 “, Trait2” 的串联;
- 'Trait2$$super$bar()' 在 FooOnSteroids 实例上调用 ...
- Trait1$class 的 'bar' 静态方法将此作为参数传递,并返回 'Trait1$$super$bar()' 方法调用和字符串 “, Trait1” 的串联;
- 'Trait1$$super$bar' on FooOnSteroids 实例,它调用 ...
- 原始的傅氏“酒吧”方法
结果是“Foo,Trait1,Trait2”。
结论
如果您已经设法阅读了所有内容,那么原始问题的答案就在前四行中......