Menu
Coddy logo textTech

다중 클래스 상속이 불가능한 이유

Coddy Java 여정의 객체 지향 프로그래밍 섹션에 포함된 레슨 — 87개 중 26번째.

Java는 클래스가 둘 이상의 클래스를 상속하는 것을 의도적으로 방지합니다. 이러한 제한은 다이아몬드 문제(Diamond Problem)라고 알려진 문제 때문에 존재합니다.

Java가 다중 상속을 허용한다고 가정해 봅시다. 다음과 같은 가상의 시나리오를 고려해 보세요:

// 이 코드는 Java에서 유효하지 않습니다
public class A {
    public void greet() {
        System.out.println("Hello from A");
    }
}

public class B extends A {
    @Override
    public void greet() {
        System.out.println("Hello from B");
    }
}

public class C extends A {
    @Override
    public void greet() {
        System.out.println("Hello from C");
    }
}

// Java에서는 허용되지 않습니다!
public class D extends B, C { }

D 객체에서 greet()를 호출하면 어떤 버전이 실행되어야 할까요? B의 것일까요, 아니면 C의 것일까요? 이러한 모호함이 바로 상속 다이어그램에 의해 형성된 다이아몬드 모양의 이름을 딴 다이아몬드 문제(Diamond Problem)입니다.

Java의 해결책은 간단합니다. 클래스의 단일 상속만 허용하는 것입니다. 하지만 Java는 대안을 제공합니다. 클래스는 여러 개의 인터페이스를 구현할 수 있으며, 이에 대해서는 다음 장에서 배우게 될 것입니다.

인터페이스는 다이아몬드 문제를 다르게 해결하며 모호함 없이 유연성을 제공합니다.

// 이것은 Java에서 유효합니다
public class Dog extends Animal implements Runnable, Comparable<Dog> {
    // 여러 인터페이스를 구현할 수 있습니다
}

이러한 설계 선택은 Java의 상속 모델을 깔끔하고 예측 가능하게 유지하는 동시에, 인터페이스를 통해 강력한 코드 재사용을 가능하게 합니다.

challenge icon

챌린지

쉬움

Java의 단일 상속 규칙을 보여주고, 이러한 제약 내에서도 어떻게 유연한 설계를 달성할 수 있는지 보여주는 음악 플레이어 시스템을 만들어 봅시다.

음악 플레이어와 음성 비서의 기능을 모두 결합한 스마트 스피커를 만든다고 가정해 보세요. Java는 여러 클래스를 상속(다중 상속)하는 것을 허용하지 않으므로, 단일 상속을 사용하여 계층 구조를 신중하게 설계해야 합니다.

코드를 정리하기 위해 네 개의 파일을 생성합니다:

  • AudioDevice.java: 모든 오디오 재생 장치가 공유하는 기본 클래스를 생성합니다. 다음을 포함해야 합니다:
    • deviceName (String)을 위한 private 필드
    • 장치 이름을 인자로 받는 생성자
    • 이름을 반환하는 getDeviceName() 메서드
    • [deviceName]: Playing audio를 출력하는 playSound() 메서드
  • MusicPlayer.java: AudioDevice를 상속하고 음악 관련 기능을 추가하는 클래스를 생성합니다:
    • currentSong (String)을 위한 private 필드
    • 장치 이름을 인자로 받고 super(deviceName)를 사용하는 생성자
    • 현재 곡을 설정하는 setSong(String song) 메서드
    • [deviceName]: Now playing - [currentSong]을 출력하도록 playSound()를 오버라이드합니다.
  • SmartSpeaker.java: MusicPlayer를 상속하는 클래스를 생성합니다 (MusicPlayer와 VoiceAssistant 클래스 둘 다를 상속하는 것이 아닙니다 - 그것은 다중 상속이 됩니다!). 스마트 스피커는 음악 플레이어에 음성 기능을 추가하여 구축됩니다:
    • assistantName (String)을 위한 private 필드
    • 장치 이름과 비서 이름을 인자로 받고 super(deviceName)를 사용하는 생성자
    • [assistantName]: Processing "[command]"를 출력하는 voiceCommand(String command) 메서드
    • [deviceName] with [assistantName] assistant를 출력하는 getFullInfo() 메서드
  • Main.java: 다단계 상속 체인을 시연합니다. 장치 이름(String), 비서 이름(String), 곡 이름(String)의 세 가지 입력을 받습니다. SmartSpeaker를 생성하고, 곡을 설정한 다음, 아래 메서드들을 순서대로 호출하세요:
    • getFullInfo()
    • playSound()
    • voiceCommand("skip to next")

장치 이름, 비서 이름, 곡 이름의 세 가지 입력을 받게 됩니다.

SmartSpeaker가 관련 없는 여러 클래스를 상속받으려 하는 대신, 체인(AudioDevice -> MusicPlayer -> SmartSpeaker)을 통해 MusicPlayer를 상속함으로써 어떻게 음악 기능을 얻게 되는지 주목해 보세요. 이것이 상속을 깔끔하고 명확하게 유지하는 Java의 방식입니다!

치트 시트

Java는 **단일 상속(single inheritance)**만 허용합니다 - 하나의 클래스는 오직 하나의 다른 클래스만 확장할 수 있습니다. 이는 클래스가 여러 부모 클래스로부터 동일한 메서드를 상속받을 경우 발생할 수 있는 모호함인 **다이아몬드 문제(Diamond Problem)**를 방지합니다.

// Java에서는 허용되지 않음 - 다중 상속
public class D extends B, C { } // 에러!

하지만 Java는 대안으로 클래스가 여러 개의 **인터페이스(interfaces)**를 구현하는 것을 허용합니다:

// Java에서 유효함
public class Dog extends Animal implements Runnable, Comparable<Dog> {
    // 하나의 클래스를 확장하고 여러 인터페이스를 구현할 수 있음
}

Java는 **다단계 상속(multilevel inheritance)**을 지원합니다 - 상속 체인을 생성합니다:

public class AudioDevice { }

public class MusicPlayer extends AudioDevice { }

public class SmartSpeaker extends MusicPlayer { }
// SmartSpeaker는 MusicPlayer와 AudioDevice 모두로부터 상속받음

직접 해보기

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        
        // 입력 읽기
        String deviceName = scanner.nextLine();
        String assistantName = scanner.nextLine();
        String songName = scanner.nextLine();
        
        // TODO: deviceName과 assistantName으로 SmartSpeaker 생성
        
        // TODO: setSong()을 사용하여 노래 설정
        
        // TODO: getFullInfo() 호출
        
        // TODO: playSound() 호출
        
        // TODO: voiceCommand("skip to next") 호출
    }
}
quiz icon실력 점검

이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.

객체 지향 프로그래밍의 모든 레슨