김찬진의 개발 블로그
[23/01/19] interface는 다중상속이 가능하지만 class는 그렇지 않은 이유? 본문
만약 B인터페이스와 C인터페이스에 이름이 동일하고 반환타입이 동일한 x메서드가 존재한다고 가정해보자.
A클래스가 B인터페이스와 C인터페이스를 implements하고 x메서드를 오버라이딩한다면 과연 어떤 인터페이스로부터 상속받은 것인지 고민할 필요가 없다. 왜냐하면 메서드의 구현에 집중해야하지 메서드의 원천을 따질 필요가 전혀 없기 때문이다. 아래 캡처를 통해 직접 확인해보자.
하지만 이전의 예시와 다르게 B인터페이스와 C인터페이스가 이름은 동일하지만 반환타입이 다른 y메서드가 존재한다고 가정해볼 경우 상황이 달라진다.
B 인터페이스와 C 인터페이스는 동일한 이름인 "y" 메서드를 정의하고 있지만, 반환 타입이 다릅니다. 따라서 A 클래스에서는 B와 C 인터페이스의 y 메서드를 각각 별도로 구현해야 한다
하지만 하나의 클래스나 인터페이스에서 메서드의 시그니처(이름과 매개변수 리스트)가 동일한 메서드를 중복해서 정의할 수 없다.
B 인터페이스의 y() 메서드 시그니처 == C 인터페이스의 y() 메서드 시그니처
어렵게 설명했지만 그냥 메서드 오버라이딩의 조건에서 탈락했을 뿐이다. (오버라이딩의 조건: 1. 동일한 이름, 2. 동일한 매개변수, 3. 동일한 반환타입). 아래 캡처를 통해 직접 확인해보자.
위와 같은 문제를 심각하게 고려하지 않아도 된다면 우리는 무엇을 고려해야 할까?
우리가 중요하게 고려해야할 것은 default method이다.
우선 디폴트 메서드에 대해서 간단히 정리하자면 디폴트 메서드는 인터페이스에 새롭게 메서드를 추가한다면 기존에 그 인터페이스를 상속하고 있는 클래스까지 수정해야 한다는 문제를 극복하고자 나온 개념이다.
만약 B인터페이스와 C인터페이스에 동일한 이름과 동일한 반환타입을 가진 디폴트메서드를 새롭게 추가한다면 A클래스는 과연 어떤 인터페이스로부터 디폴트메서드를 상속받은것인지 분간할 수 없다는 것이다.
이러한 문제를 다이아몬드 문제라고 부른다.
그렇다면 이 다이아몬드 문제를 A클래스가 어떻게 해결해야 할까?
이 문제는 A클래스가 디폴트메서드를 @Override함으로써 간단히 극복할 수 있다.
이러한 일련의 과정들이 클래스의 다중상속을 금지시킨 이유를 명확히 보여주고 있다. 아래 캡처를 통해 직접 확인해보자.
클래스의 다중상속을 금지한 이유를 예를 들어 좀 더 자세히 설명해보자. 실제로는 불가능하지만 설명을 위해 클래스의 다중상속이 가능하다고 가정해보자. D클래스와 E클래스에서 동일한 이름과 동일한 반환타입을 가진 z메서드를 구현했고, C클래스가 D클래스와 E클래스를 상속한다고 가정한다. 이 경우 어떤 클래스로부터 상속받은 z메서드인지 C클래스가 분간할 수 없다. 앞서 말했듯이 D클래스와 E클래스는 z메서드를 구현했고 A인터페이스와 B인터페이스는 z메서드를 선언만 했기 때문이다. (만약 D클래스와 E클래스가 아니라 A인터페이스와 B인터페이스였다면 상속의 원천을 따질 것이 아니라 메서드의 구현에 초점을 맞추기만 하면 되었기 때문이다.)
'1일1배움 > Java' 카테고리의 다른 글
23/07/14 [Collection? Collections? Iterable? Iterator?] (0) | 2023.01.29 |
---|---|
23/01/23 [iterator?] (0) | 2023.01.23 |
23/01/19 [얕은복사? 깊은복사?] (0) | 2023.01.19 |
23/01/19 [Serializable?] (0) | 2023.01.19 |
23/01/19 [equals() 오버라이딩?] (0) | 2023.01.19 |