상속은 객체지향의 중요한 특징 중 하나이다. 하지만 언어에 따라 상속을 지원하는 방식이 다르며, 잘못 설계하면 심각한 문제가 발생할 수 있다. 심각한 문제 중 대표적인 것이 바로 다이아몬드 문제(Diamond Problem)이다.
다이아몬드 문제란?
"다이아몬드 문제"는 다중 상속(Multiple Inheritance)을 지원하는 언어에서 발생하는 모호성 문제이다.
예시
Animal
/ \
Dog Cat
\ /
Hybrid
- Hybrid 클래스가 Dog, Cat을 동시에 상속한다.
- Dog와 Cat은 모두 Animal을 상속한다.
- 이제 Hybrid 객체에서 Animal의 메서드를 호출하면?
- Dog를 통해 상속된 것인지
- Cat을 통해 상속된 것인지
- 모호해진다. → 컴파일러/런타임 오류가 발생할 수 있다.
- 다중 상속 구조가 "마름모(◆)"처럼 생겨서 다이아몬드 문제라고 불린다.
자바에서 다이아몬드 문제가 없는 이유
자바는 클래스에 대한 다중 상속을 허용하지 않는다.
class A {}
class B extends A {}
class C extends A {}
// class D extends B, C {} // 불가능! (컴파일 오류)
- 자바는 extends로 단일 상속만 허용한다.
- 따라서 클래스 계층 구조에서 다이아몬드 문제가 발생하지 않는다.
- 대신, 자바는 인터페이스 다중 구현을 허용한다.
인터페이스와 다이아몬드 문제
인터페이스는 다중 구현이 가능하다. 그렇다면 다이아몬드 문제가 생길까?
interface A { void hello(); }
interface B extends A {
@Override
default void hello() { System.out.println("B.hello"); }
}
interface C extends A {
@Override
default void hello() { System.out.println("C.hello"); }
}
class D implements B, C {
// 다이아몬드 문제!
}
- D는 B, C를 동시에 구현하고 있다.
- B, C 둘 다 hello()를 가지고 있기 때문에 호출 시 모호성이 발생한다.
자바의 해결 방식
자바 컴파일러는 이 문제를 해결하기 위해 명시적으로 재정의(override)하도록 강제한다.
class D implements B, C {
@Override
public void hello() {
// 선택적으로 호출 가능
B.super.hello(); // B 버전 호출
// C.super.hello(); // C 버전 호출
}
}
- 다중 인터페이스 상속에서 같은 default 메서드가 충돌하면 자식 클래스가 반드시 오버라이딩해야 한다.
- super 키워드로 원하는 상위 인터페이스 구현을 선택적으로 호출할 수 있다.
- 즉, 자바는 인터페이스 다이아몬드 문제를 개발자가 직접 해결하게 한다.
정리하자면...
- 다이아몬드 문제: 다중 상속에서 상위 클래스가 중복되어 모호성 발생
- 자바 클래스: 단일 상속만 허용 → 다이아몬드 문제 없음
- 자바 인터페이스: 다중 구현 가능 → 충돌 발생 시 오버라이딩으로 해결
- 실무 원칙
- 클래스는 상속보다 조합(Composition) 우선
- 인터페이스 다중 구현은 규약 설계에 유용, 충돌 시 반드시 명시적 해결
- 자바는 클래스 단일 상속으로 다이아몬드 문제를 원천 차단하고,
- 인터페이스에서는 오버라이딩 강제를 통해 명시적 해결을 유도한다.
'java' 카테고리의 다른 글
| Java 다형성(Polymorphism) 심화: 추상 클래스와 인터페이스 (0) | 2025.09.16 |
|---|---|
| Java 다형성(Polymorphism) 기초 정리 (0) | 2025.09.15 |
| Java 상속(Inheritance) 정리 (0) | 2025.09.15 |
| Java final 키워드 정리 (2) | 2025.09.15 |
| Java 메모리 구조와 static 정리 (0) | 2025.09.15 |