在Java中使用Scala特性和实现的方法

我想这是不可能调用从Java实现的Scala特性的方法,或者有办法吗?

假设我在Scala中:

trait Trait { def bar = {} } 

在Java中如果我使用它

 class Foo implements Trait { } 

Java抱怨Trait is not abstract and does not override abstract method bar() in Trait

回答

从Java的angular度来看, Trait.scala被编译到Trait 界面 。 因此,在Java中实现Trait被解释为实现一个接口 – 这使得你的错误信息变得明显。 简短的回答:你不能利用Java中的trait实现,因为这将启用Java中的多重inheritance(!)

它在Scala中如何实现?

长的答案:那么它在Scala中如何工作? 查看生成的字节码/类可以find以下代码:

 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混淆)类是透明创build的,在技术上不会实现Trait接口。 然而,它确实有一个static bar()方法以Trait实例作为参数(sorting)
  • Foo实现了Trait界面
  • scalac通过委托给Trait$class自动实现Trait方法。 这基本上意味着调用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(){}}; 

Trait1Trait2也将成为扩展Trait接口。 现在如果在定义FooTrait2最后一个:

 class Foo extends Trait1 with Trait2 

你会得到:

 class Foo implements Trait1, Trait2 { public void bar() { Trait2$class.bar(this); //works because `this` implements Trait2 } } 

但是,切换Trait1Trait2 (使Trait1为最后)将导致:

 class Foo implements Trait2, Trait1 { public void bar() { Trait1$class.bar(this); //works because `this` implements Trait1 } } 

可堆叠修改

现在考虑作为可堆叠修改的特性是如何工作的。 想象一下,有一个非常有用的类Foo:

 class Foo { def bar = "Foo" } 

你想用一些新的function来丰富你的特质:

 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 

它转化为:

Trait1

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

Trait2

 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'静态方法将此参数作为parameter passing,并返回'Trait2 $$ super $ bar()'方法调用和string“Trait2”的串联。
  • 'Trait2 $$ super $ bar()'在FooOnSteroids实例调用…
  • Trait1 $ class的'bar'静态方法将此参数作为parameter passing,并返回'Trait1 $$ super $ bar()'方法调用和string“Trait1”的串联。
  • 调用FooOnSteroids实例的'Trait1 $$ super $ bar'…
  • 原来的Foo的“酒吧”方法

结果是“Foo,Trait1,Trait2”。

结论

如果你已经设法阅读所有的东西,最初的问题的答案是前四行

因为bar正在返回一个空Unit (一种NOP),所以确实不是抽象的。 尝试:

 trait Trait { def bar: Unit } 

然后bar会是一个返回void的Java抽象方法。