JDK 8의 기본값은 Java에서 다중 상속의 한 형태입니까?


83

JDK 8의 새로운 기능을 사용하면 바이너리 호환성을 유지하면서 기존 인터페이스에 추가 할 수 있습니다.

구문은 다음과 같습니다.

public interface SomeInterface() {
  void existingInterface();
  void newInterface() default SomeClass.defaultImplementation;
}

이러한 방식으로 기존의 모든 구현 SomeInterface에서이 새 버전으로 업그레이드 할 때 갑자기 newInterface().

이것은 깔끔하지만 구현하지 않은 새로운 기본 메서드를 추가 한 두 개의 인터페이스를 구현할 때 어떤 일이 발생합니까? 예를 들어 설명하겠습니다.

public interface Attendance {
   boolean present() default DefaultAttendance.present;
}

public interface Timeline {
   boolean present() default DefaultTimeline.present;
}

public class TimeTravelingStudent implements Attendance, Timeline {

}

// which code gets called?
new TimeTravelingStudent().present();

아직 JDK 8의 일부로 정의 되었습니까?

나는 http://cs.oswego.edu/pipermail/lambda-lib/2011-February/000068.html 에서 비슷한 것에 대해 이야기하는 자바 신을 찾았 지만 개인 메일 링 목록의 일부이며 직접 요청할 수 없습니다.

JDK 8에서 기본값을 사용하는 방법과 람다를 지원하도록 Collection 인터페이스를 확장하는 방법에 대한 자세한 내용은 https://oracleus.wingateweb.com/published/oracleus2011/sessions/25066/25066_Cho223662.pdf를 참조하십시오.


시청할 비디오 세션은 여기에 있습니다. medianetwork.oracle.com/video/player/1113272518001 이것은 디자이너가 Virtual Extensions라는 기능에 대해 이야기하고 있습니다. 그는 또한 이것이 이전 버전과의 호환성을 깨지 않는 방법에 대해서도 이야기합니다.
Peter Lawrey 2011 년

따라서 내 예제에 대한 대답은 현재 컴파일러 오류가 발생한다는 것입니다. 그러나 그들은 다른 솔루션에 열려 있습니다.
Pyrolistical

이것에 대한 또 다른 유용한 물질이다 cr.openjdk.java.net/~briangoetz/lambda/...
MohamedSanaulla

참고 : 인터페이스 메서드의 기본 구현에 대한 최종 구문은 다른 것으로 밝혀졌습니다 (외부 클래스에 대한 참조 대신 코드 블록).
Joachim Sauer

4
Java는 항상 여러 유형의 상속을 가지고 있습니다 . 기본 메서드는 동작의 다중 상속을 추가 하지만 상태 는 추가 하지 않습니다 . (문제의 대부분이 어디에서 오는지 C ++와 같은 언어에서 국가의 여러 상속입니다.)
브라이언 게츠

답변:


66

복제 작업에 대한 대답은 다음과 같습니다.

다중 상속 문제를 해결하려면 동일한 메서드 이름과 서명에 대한 기본 구현을 제공하는 두 인터페이스를 구현하는 클래스가 메서드 구현을 제공해야합니다. [전체 기사]

귀하의 질문에 대한 제 대답은 다음과 같습니다. 예, 여러 부모로부터 행동을 상속받을 수 있기 때문에 다중 상속의 한 형태입니다. 빠진 것은 상태, 즉 속성을 상속하는 것입니다.


2
+1 : 충돌이있을 때 덜 구체적인 구현보다 더 구체적인 구현을 취하여 충돌이있을 경우 어떤 구현이되어야하는지 지정할 수 있습니다.
Peter Lawrey 2011 년

@ H-Man2 이해가 안 돼요. 그것이 사실이라면 바이너리 호환성을 깨뜨릴 것임을 의미합니다. 이제는 다중 상속을 방지하기 위해 이진 호환성을 깨는 것만 큼 나쁘지 않을 수 있습니다.
Pyrolistical

@PeterLawrey 내 예에서 어느 것이 더 구체적입니까?
Pyrolistical

@Pyrolistical : 아니요, 컴파일러가 기본 구현을 일반 메서드 호출로 변환 할 수 있으므로 호환성이 깨지지 않습니다. 나는 그것이 실제 상속보다 매크로라고 생각하지만 다중 상속의 측면을 시뮬레이션 할 수 있습니다. Peter의 비디오가 더 자세한 답변을 제공 할 수 있습니다.
H-Man2

실제로 우리는 추상적 인 getter 및 setter를함으로써 누락 된 상태를 주변에 얻을 수있는, 상태를 추가 할 수있는 구현 클래스는 ...
vikkyhacks

8

나는 이것이 오래된 게시물이라는 것을 알고 있지만, 나는이 일을하고 있기 때문에 ...

컴파일러에서 다음과 같은 오류가 발생합니다.

 TimeTravelingStudent 클래스는 출석 유형에서 present ()에 대한 관련없는 기본값을 상속하고 현재에 대한 타임 라인 참조가 모호합니다. 둘 다 타임 라인의 present () 메서드와 출석 일치의 메서드 present ()입니다.


7

거기 시나리오 :

1) 먼저 언급했는데 가장 구체적인 인터페이스없는 경우

public interface A {
   default void doStuff(){ /* implementation */ }
}

public interface B {
   default void doStuff() { /* implementation */ } 
}

public class C implements A, B {
// option 1: own implementation
// OR
// option 2: use new syntax to call specific interface or face compilation error
  void doStuff(){
      B.super.doStuff();
  }
}

2) 둘째, 보다 구체적인 인터페이스가있는 경우 :

   public interface A {
       default void doStuff() { /* implementation */ } 
    }

    public interface B extends A {
       default void doStuff() { /* implementation */ } 
    }

    public class C implements A, B {
    // will use method from B, as it is "closer" to C
    }

4

귀하의 질문에 대한 제 대답은 다음과 같습니다. 예, 여러 부모로부터 행동을 상속받을 수 있기 때문에 다중 상속의 한 형태입니다. 빠진 것은 상태, 즉 속성을 상속하는 것입니다.

예,하지만 구현 클래스가 구현해야하는 인터페이스에 getter 및 setter를 추가 할 수 있습니다. 그럼에도 불구하고 구현 클래스는 속성을 상속하지 않습니다. 따라서 AFAICS는 다중 상속 스타일 솔루션이 아니라 특성 스타일 솔루션과 비슷합니다.


4

요컨대, 컴파일 시간 오류이며 구현시 수동으로 메서드를 재정의해야합니다.


기본 방법의 목적

Java 8에 기본 메소드를 도입하는 주요 목적은 기존 구현을 손상시키지 않고 인터페이스를 확장 가능하게 만드는 것입니다 (타사 Java 라이브러리가 너무 많습니다).

그리고 multiple inheritanceC ++에서 와 같이 실제로는 피하도록되어 있습니다. 이것은 자바에서 기본 메소드의 목적이 아닙니다.


재정의하는 방법

2 가지 옵션 :

  • 자체 논리로 메서드를 재정의합니다.
  • 메서드를 재정의하고 super, 형식을 통해 인터페이스의 메서드 중 하나를 호출 합니다.<interface_name>.super.<method_name>();

팁 :

  • 인터페이스의 메소드는 기본적으로 공용이므로 public재정의 할 때 키워드 를 추가하는 것을 잊지 마십시오 .

2

누군가가 여전히 답을 찾고 있다면, 클래스가 동일한 기본 메소드로 두 개의 인터페이스를 구현하는 경우 클래스는 자체 구현을 제공하여 명확성을 해결해야합니다. 기본 메서드의 상속이 작동하는 방법에 대한 자세한 내용 은 자습서를 참조하십시오.


0

"어떻게 메소드를 구별 할 것인가"는 Stackoverflow에 제기 된 질문 이며 Java1.8 인터페이스의 구체적인 메소드를 참조했습니다.

다음은 그 질문에 답해야하는 예입니다.

interface A{
default public void m(){
System.out.println("Interface A: m()");
}
}

interface B{
default public void m(){
System.out.println("Interface B: m()");
}
}

 class C implements A,B { 

 public void m(){
  System.out.println("Concrete C: m()");   
 }

public static void main(String[] args) {
   C aC = new C();
   aC.m();
   new A(){}.m();
   new B(){}.m();
}
}

위의 클래스 C 는 인터페이스 A와 B 의 고유 한 구체적인 방법구현해야합니다 . 즉 :

 public void m(){
  System.out.println("Interface C: m()");   
 }

통화에 구체적인 구현방법 A로부터 특정 인터페이스를 수행 할 수 있습니다 인스턴스화 인터페이스를 하고 명시 적으로 호출 구체적인 방법을 이의 인터페이스를

예를 들어 다음 코드는 인터페이스 A 에서 m () 메서드 의 구체적인 구현을 호출합니다 .

new A(){}.m();

위의 출력은 다음과 같습니다.

인터페이스 A : m ()


-1

내가 보는 한, 상태 비 저장이기 때문에 다중 상속이 아닙니다. 따라서 가상 확장 메서드는 전체 개체 또는 클래스 기능을 지원하지 않습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.