is-a와 has-a

홍성덕·2025년 1월 14일

"is-a"와 "has-a"는 객체 지향 프로그래밍(Object-Oriented Programming, OOP)에서 클래스 간의 관계를 설명할 때 사용되는 개념이다.

1. is-a

is-a는 말그대로 "A는 B이다"와 같다.
is-a는 한 클래스가 다른 클래스를 상속받을 때 사용하는 개념이다.
A 클래스가 B 클래스의 파생 클래스라는 관계를 나타내는 개념이다.

예를 들어,
고양이는 동물이다.
강아지는 동물이다.
처럼 말이다.

class Animal {
    void eat() { /* ... */ }
}

class Cat extends Animal {
}

class Dog extends Animal {
}

2. has-a

has-a는 "A가 B를 소유하고 있다"라는 의미이다.
has-a는 한 클래스가 다른 클래스를 소유하거나 포함하는 관계를 나타내는 개념이다.

class Engine {
    void start() { /* ... */ }
}

class Car {
    private Engine engine;

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

    void startCar() {
        engine.start();
    }
}

예를 들어 이와 같이 자동차 클래스는 엔진을 포함하고 있으므로 자동차는 엔진과 has-a 관계에 놓여있다.

다른 예시로는 어떠한 Util 클래스를 다른 클래스에서 가져다 사용한다면, 사용하는 클래스는 Util 클래스를 포함하고 있으므로 둘이 has-a 관계라고 설명할 수 있다. 이 둘은 상속 관계가 아닌 별도의 클래스이다.


has-a 관계라면 Delegation(위임) 패턴을 통해 자신이 보유하고 있는 객체에게 작업을 위임할 수 있다.

Delegation(위임)이란?

Delegation은 한 객체가 특정 작업을 직접 수행하지 않고, 자신의 보유 객체(구성 요소)에게 그 작업을 위임하여 처리하도록 하는 방식이다. 이를 통해 객체는 자신의 역할에 집중하고, 보유 객체(구성 요소)는 전문화된 기능을 수행할 수 있다.

class Engine {
    void start() {
        System.out.println("엔진이 시동되었습니다.");
    }
}

class Car {
    private Engine engine;

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

    // Delegation: Car가 Engine 객체에게 start 메소드 호출을 위임
    void startEngine() {
        engine.start();
    }
}

public class Main {
    public static void main(String[] args) {
        Car car = new Car();
        car.startEngine(); // "엔진이 시동되었습니다." 출력
    }
}

예를 들어 위와 같이 Car 클래스가 Engine 클래스를 포함하고 있으므로 이 둘은 has-a 관계이다. (Car has Engine)

Car 객체는 자신의 Engine 객체에게 start 메소드 호출을 위임한다. 이렇게 함으로써 Car 클래스는 Engine 클래스의 내부 구현을 신경쓸 필요 없이 Car 클래스의 기능을 효율적으로 구현 가능하다.


참고자료

profile
안드로이드 주니어 개발자

0개의 댓글