Java

다중 상속

뽀루피 2024. 7. 17. 17:00

다중 상속이란?

한 클래스가 두 개 이상의 부모 클래스로부터 특성을 상속받는 개념이다.

Java에서는 클래스의 다중 상속을 직접적으로 지원하지는 않지만 인터페이스를 통해 유사한 효과를 낼 수 있다.

 

 

장점

  • 코드 재사용성 증가
  • 다양한 부모 클래스의 특성을 조합 가능

단점

  • 다이아몬드 상속 문제: 같은 메소드가 여러 부모 클래스에 존재할 때 발생하는 모호성이 존재한다
  • 복잡성 증가: 클래스 계층 구조가 복잡해질 수 있다.

 

 

Java에서의 인터페이스를 통한 다중 상속 구현:

 

여러 인터페이스에서 같은 시그니처의 디폴트 메소드가 있을 경우 충돌이 발생할 수 있다.

이럴 경우 메소드를 명시적으로 선택해줘야한다.

interface Interface1 {
    default void commonMethod() {
        System.out.println("Interface1");
    }
}

interface Interface2 {
    default void commonMethod() {
        System.out.println("Interface2");
    }
}

class MyClass implements Interface1, Interface2 {
    @Override
    public void commonMethod() {
        Interface1.super.commonMethod(); // 명시적으로 선택
    }
}

 

 

충돌 해결

  • 이름을 다르게 지어주거나
interface Interface1 {
    void method1();
}

interface Interface2 {
    void method2();
}

class MyClass implements Interface1, Interface2 {
    public void method1() {
        System.out.println("Method 1");
    }

    public void method2() {
        System.out.println("Method 2");
    }
}

 

 

 

  • 컴포지션(Composition)으로도 대체 할 수 있다.

         *컴포지션: 한 클래스가 다른 클래스의 객체를 포함하는 방식

class Engine {
    void start() {
        System.out.println("Engine started");
    }
}

class Car {
    private Engine engine;

    public Car() {
        this.engine = new Engine();
    }

    void startCar() {
        engine.start();
        System.out.println("Car is ready to go");
    }
}

 

위의 예시에서 Car 클래스는 Engine 클래스를 포함하고 있다.

 

 

  • 인터페이스와 추상 클래스의 조합
interface Attackable {
    void attack();
    void move();
}

abstract class GameCharacter implements Attackable {
    protected int health;

    public GameCharacter() {
        this.health = 100;
    }
    
    public void move() {...}
    // attack() 메소드는 자식 메소드에서 구체적으로 구현하도록 추상 클래스에서 구현하지 않음

    // 추상 메서드 - 각 캐릭터 클래스에서 구현해야 함
    abstract void useSpecialAbility();
}

// 인터페이스 + 추상 클래스 상속
class Warrior extends GameCharacter {
    public Warrior() {}

    @Override
    public void attack() {
        System.out.println("Attack!");
    }

    @Override
    void useSpecialAbility() {
        System.out.println("uses Berserk Rage!");
    }
}

 

인터페이스와 추상 클래스의 조합에는 이러한 장점이 있다.

  • 유연성: 새로운 캐릭터 타입을 쉽게 추가할 수 있다. (Warrior, Healer, Magician 등등)
  • 코드 재사용: 공통 기능은 추상 클래스에서 구현되어 중복을 줄입니다.
  • 다형성: 인터페이스 추가로 다양한 객체를 다룰 수 있습니다.
  • 확장성: 새로운 기능(예: Healable 인터페이스)을 쉽게 추가할 수 있습니다.