在Java中使用Scala traits和已实现的方法 [英] Using Scala traits with implemented methods in Java

查看:96
本文介绍了在Java中使用Scala traits和已实现的方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I guess it is not possible to invoke methods implemented in Scala traits from Java, or is there a way?

假设我有Scala:

trait Trait {
  def bar = {}
}

如果我用它作为

class Foo implements Trait {
}

Java抱怨 Trait不是抽象的,并且不会覆盖Trait中的抽象方法bar()

推荐答案

答案



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

Answer

From Java perspective Trait.scala is compiled into Trait interface. Hence implementing Trait in Java is interpreted as implementing an interface - which makes your error messages obvious. Short answer: you can't take advantage of trait implementations in Java, because this would enable multiple inheritance in Java (!)

长答案:那么它如何在Scala中运行?查看生成的字节码/类,可以找到以下代码:

Long answer: so how does it work in Scala? Looking at the generated bytecode/classes one can find the following code:

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 是一个界面

  • abstract Trait $ class (不要与 Trait.class 混淆)透明创建,从技术上讲,实现 Trait 界面。但它确实有一个静态bar()方法,将 Trait 实例作为参数(排序这个

  • Foo 实现 Trait 界面

  • scalac 通过委托 Trait 方法>性状$类。这实际上意味着调用 Trait $ class.bar(this)

    • Trait is an interface
    • abstract Trait$class (do not confuse with Trait.class) class is created transparently, which technically does not implement Trait interface. However it does have a static bar() method taking Trait instance as argument (sort of this)
    • Foo implements Trait interface
    • scalac automatically implements Trait methods by delegating to Trait$class. This essentially means calling Trait$class.bar(this).
    • 注意那个 Trait $ class 既不是 Foo 的成员,也不是 Foo 扩展它。它通过传递这个来代表它。

      Note that Trait$class is neither a member of Foo, nor does Foo extend it. It simply delegates to it by passing this.

      继续关于Scala如何工作的题外话...据说很容易想象多种特征的混合如何在下面起作用:

      To continue the digression on how Scala works... That being said it is easy to imagine how mixing in multiple traits works underneath:

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



      多个特征重写相同的方法



      现在很容易想象多种特征的混合如何覆盖相同的方法:

      Multiple traits overriding same method

      Now it's easy to imagine how mixing in multiple traits overriding same method:

      trait Trait {def bar(){}};
      trait Trait1 extends Trait {override def bar(){}};
      trait Trait2 extends Trait {override def bar(){}};
      

      再次 Trait1 Trait2 将成为扩展 Trait 的接口。现在如果 Trait2 在定义 Foo 时最后出现:

      Again Trait1 and Trait2 will become interfaces extending Trait. Now if Trait2 comes last when defining 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 为最后一次)将结果:

      However switching Trait1 and Trait2 (making Trait1 to be last) will result in:

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



      可堆叠的修改



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

      Stackable modifications

      Now consider how traits as stackable modifications work. Imagine having a really useful class Foo:

      class Foo {
        def bar = "Foo"
      }
      

      您希望使用特征丰富一些新功能:

      which you want to enrich with some new functionality using traits:

      trait Trait1 extends Foo {
        abstract override def bar = super.bar + ", Trait1"
      }
      
      trait Trait2 extends Foo {
        abstract override def bar = super.bar + ", Trait2"
      }
      

      以下是关于类固醇的新'Foo':

      Here is the new 'Foo' on steroids:

      class FooOnSteroids extends Foo with Trait1 with Trait2
      

      它转换为:

      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



      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



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

      所以整个堆栈调用如下:

      So the whole stack invocations are as follows:


      • FooOnSteroids实例上的'bar'方法(入口点);

      • Trait2 $ class's'bar'static方法将此作为参数传递并返回'Trait2 $$ super $ bar()'方法调用和字符串,Trait2的串联;

      • 'Trait2 $$ super $ bar()'在FooOnSteroids实例上调用...

      • Trait1 $ class的'bar'静态方法将此作为参数传递并返回'Trait1 $$ super $ bar()'方法调用和字符串的串联,Trait1;

      • 'FooOnSteroids实例上的'Trait1 $$ super $ bar'调用...

      • 原始Foo的'bar'方法

      • 'bar' method on FooOnSteroids instance (entry point);
      • Trait2$class's 'bar' static method passing this as argument and returning a concatenation of 'Trait2$$super$bar()' method call and string ", Trait2";
      • 'Trait2$$super$bar()' on FooOnSteroids instance which calls ...
      • Trait1$class's 'bar' static method passing this as argument and returning a concatenation of 'Trait1$$super$bar()' method call and string ", Trait1";
      • 'Trait1$$super$bar' on FooOnSteroids instance which calls ...
      • original Foo's 'bar' method

      结果是Foo,Trait1,Trait2。

      And the result is "Foo, Trait1, Trait2".

      如果你已经设法阅读了所有内容,原始问题的答案就在前四行......

      If you've managed to read everything, an answer to the original question is in the first four lines...

      这篇关于在Java中使用Scala traits和已实现的方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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