← SEARCHABLE ARCHIVE
Java · 2026-07-26

Java 기초부터 마스터까지 — 4화

상속과 인터페이스로 다형성 사용하기

INTERACTIVE READING MODE →

본 블로그 작성 글들은, 강의를 목표로 하고 제작되었습니다. 또한 작성된 글의 정보도 틀렸을 수 있으니, 주의해주세요.

여러 객체가 같은 방식으로 사용되어야 할 때 인터페이스와 상속을 이용할 수 있다. 호출하는 코드는 구체적인 클래스보다 필요한 역할에 의존하는 편이 변경에 강하다.

인터페이스

public interface Damageable {
    boolean isAlive();
    void takeDamage(int amount);
}

public final class Monster implements Damageable {
    private int health = 100;

    @Override
    public boolean isAlive() {
        return health > 0;
    }

    @Override
    public void takeDamage(int amount) {
        health = Math.max(0, health - amount);
    }
}

공격 코드는 Monster가 아니라 Damageable을 받으면 된다. 나중에 파괴 가능한 상자를 추가해도 같은 계약으로 처리할 수 있다.

추상 클래스와 상속

public abstract class Skill {
    private final String name;

    protected Skill(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public abstract void execute(Damageable target);
}

추상 클래스는 공통 상태와 구현을 공유하면서 일부 동작을 자식에게 맡길 수 있다. 상속은 부모의 규칙까지 결합하므로 단순한 코드 재사용만을 위해 깊게 만들면 변경 범위가 커진다.

다형성

List<Damageable> targets = List.of(
    new Monster(),
    new TrainingDummy()
);

for (Damageable target : targets) {
    target.takeDamage(10);
}

같은 호출을 해도 실제 객체에 맞는 구현이 실행된다. 호출자는 instanceof로 모든 구체 타입을 나열하지 않아도 된다.

인터페이스는 역할을 표현하고 추상 클래스는 공통 기반을 제공한다. 구성이 가능한 작은 객체를 조합할 수 있다면 상속보다 그 방법이 더 단순한 경우도 많다.