ProgramingTip

Java에서 구현 된 메서드와 함께 Scala 특성 사용

bestdevel 2020. 12. 7. 20:28
반응형

Java에서 구현 된 메서드와 함께 Scala 특성 사용


Java에서 Scala 특성으로 구현 된 메서드를 호출 할 수 있다고 생각합니다. 아니면 어디입니까?

Scala에 안전한 가정합니다.

trait Trait {
  def bar = {}
}

그리고 Java로 사용하면

class Foo implements Trait {
}

자바는 다음과 같이 불평합니다. Trait is not abstract and does not override abstract method bar() in Trait


대답

자바에서 관점 인터페이스Trait.scala 로 컴파일됩니다 . 따라서 Java에서는 구현하는 해석되어 오류 메시지를 분명히 만듭니다. 짧은 대답 : Java (!)에서 다중 상속을 가능하게 Java에서 특성 구현을 사용할 수 없습니다.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 인터페이스입니다
  • abstract Trait$class(혼동하지 않고 Trait.class) 클래스는 기술적으로 인터페이스를 구현 하지 않는 투명하게 생성 Trait합니다. 그러나 인스턴스를 인수로 static bar()취하는 메소드 가 있습니다 Trait(일종의 this)
  • FooTrait인터페이스 구현
  • scalacTrait에 의해 방법을 자동으로 구현 합니다 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
    }
}

그러나 전환 Trait1Trait2( Trait1마지막으로 만들기 ) 결과는 다음과 가변적입니다.

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

쌓을 수있는 수정

이제 스택 가능한 수정으로 특성이 작동하는 방식을 고려하십시오. 정말 유용합니다.

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"의 연결을 반환합니다.
  • ...를 호출하는 FooOnSteroids 인스턴스의 'Trait2 $$ super $ bar ()'
  • Trait1 $ class의 'bar'정적 메서드는 이것을 인수로 전달하고 'Trait1 $$ super $ bar ()'메서드 호출과 문자열 ", Trait1"의 연결을 반환합니다.
  • 호출하는 FooOnSteroids 인스턴스의 'Trait1 $$ super $ bar'...
  • 원래 Foo의 'bar'방법

결과는 "Foo, Trait1, Trait2"입니다.

결론

모든 것을 읽었다면 원래 질문에 대한 답은 처음 네 줄에 있습니다.


barUnit(일종의 NOP)을 반환하기 때문에 실제로 추상 아닙니다 . 시험:

trait Trait {
  def bar: Unit
}

그런 다음 bar을 반환하는 Java 추상 메서드가 void됩니다.

참고 URL : https://stackoverflow.com/questions/7637752/using-scala-traits-with-implemented-methods-in-java

반응형