왜 클래스는 단일 상속만 가능한데, 인터페이스는 2개 이상 구현이 가능할까요?

다이아몬드 문제(Diamond Problem) 때문입니다.

다이아몬드 문제란?

        Animal
       /      \
    Dog        Cat
       \      /
        ???
// 만약 다중 상속이 가능하다면?
class Animal {
    public void sound() { System.out.println("..."); }
}

class Dog extends Animal {
    @Override
    public void sound() { System.out.println("멍멍"); }
}

class Cat extends Animal {
    @Override
    public void sound() { System.out.println("야옹"); }
}

// X 다중 상속 시 어떤 sound()를 호출해야 할지 모호함
class DogCat extends Dog, Cat {
    // Dog의 sound()? Cat의 sound()?  → 컴파일러가 결정 불가 X
}

인터페이스는 왜 괜찮을까?

// 인터페이스는 구현이 없으므로 충돌 자체가 발생하지 않음
interface Flyable  { void fly(); }
interface Swimmable { void swim(); }

// 구현은 클래스가 직접 → 모호성 없음
class Duck implements Flyable, Swimmable {
    public void fly()  { ... }  // Duck이 직접 결정
    public void swim() { ... }  // Duck이 직접 결정
}

Java 8 default 메서드 - 예외 상황

// default 메서드는 구현이 있어서 충돌 가능
interface A {
    default void hello() { System.out.println("A"); }
}

interface B {
    default void hello() { System.out.println("B"); }
}

// X 컴파일 에러 - 어떤 hello()를 써야 할지 모호
class C implements A, B { }

// O 직접 오버라이드로 해결
class C implements A, B {
    @Override
    public void hello() {
        A.super.hello();  // 명시적으로 선택
    }
}

정리

클래스인터페이스
구현 보유O 있음X 없음 (default 제외)
다이아몬드 문제발생 X발생 안 함 O
다중 허용XO
클래스 다중 상속 X  →  구현 충돌(다이아몬드 문제) 발생
인터페이스 다중 구현 O  →  구현이 없으니 충돌 없음
                           (구현 책임은 클래스에게)

결국 핵심은 "구현의 유무" 입니다. 인터페이스는 구현이 없기 때문에 여러 개를 구현해도 무엇을 실행할지 항상 명확합니다.

CSLOG에서 보기