자바에서는 왜 다중상속을 허용하지 않는걸까? 그리고 어떻게 인터페이스를 통해서는 다중상속이 가능한걸까?
이를 알아보기 위해 아래와 같은 상속관계를 갖는 클래스들을 생성해보겠다.
Child -> Mother -> GrandMother
, Father -> GrandMother
Person.java
1 | public class Person { |
Father.java
1 | public class Father extends Person { |
Mother.java
1 | public class Mother extends Person { |
Child.java
1 | public class Child extends Mother { |
Child
의 main()
를 실행한 결과는 다음과 같다.
1 | 내 국적은 대한민국입니다. |
Child
클래스의 인스턴스를 사용해서 가문()
과 nation
필드를 출력했는데, 둘다 Child
클래스에 선언된 필드가 아니다. GrandMother
클래스에 선언된 필드를 Mother
클래스의 상속을 거쳐 Child
까지 상속된것이다.
자바에서 다중상속이 안되는 이유
만약 자바에서 다중상속이 허용되어서 Child
가 Mother
과 Father
를 모두 상속한다고 가정해보자.
위와 같은 상속 관계에서 Child
는 Father
와 Mother
의 멤버 필드와 메소드를 상속받을 것이다. 그런데 Father
와 Mother
에 같은 메소드가 있다면 어떨까? Father
와 Mother
는 Person
을 상속받으면서 가문()
을 서로 다르게 오버라이딩했다.
그렇다면 Father와 Mother를 상속받는 Child에서 child.가문()
은 어떤걸 출력할까?
이 애플리케이션을 실행해야하는 JVM에서는 Father
에도 선언되어 있고, Mother
에도 선언되어 있는 가문()
중 어떤걸 Child
가 상속받아야하는지를 모르기 때문에 컴파일 에러가 발생한다.
그래서 자바에서 다중상속이 안되는 이와 같은 문제를 다이아몬드 문제라고한다.
인터페이스를 통한 다중상속은 가능한 이유
구현체를 갖고있는 메소드 상속이 불가능하다면 구현체가 없는 추상메소드만 있는 인터페이스는 어떨까?
Person.java
1 | public interface Person { |
Father.java
1 | public interface Father extends { |
Mother.java
1 | public interface Mother extends Person { |
Child.java
1 | public class Child implements Father, Mother { |
이 코드는 컴파일 에러 없이 실행가능했다. 자바에서 다중상속(extends
)은 안되는데, 왜 인터페이스를 통한 다중상속(implements
)은 가능한걸까?
상속받은 메소드가 구현체가 없는 추상 메소드이기 때문이다. 어차피 구현체가 없기 때문에 Child
가 상속받은 메소드가 Father
로부터 받은건지, Mother
로부터 받은건지 알필요가 없다. 어차피 상속받은 객체인 Child
에서 구현을 할 것이기 때문이다.