"is-a"와 "has-a"는 객체 지향 프로그래밍(Object-Oriented Programming, OOP)에서 클래스 간의 관계를 설명할 때 사용되는 개념이다.
is-a는 말그대로 "A는 B이다"와 같다.
is-a는 한 클래스가 다른 클래스를 상속받을 때 사용하는 개념이다.
A 클래스가 B 클래스의 파생 클래스라는 관계를 나타내는 개념이다.
예를 들어,
고양이는 동물이다.
강아지는 동물이다.
처럼 말이다.
class Animal {
void eat() { /* ... */ }
}
class Cat extends Animal {
}
class Dog extends Animal {
}
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 클래스의 기능을 효율적으로 구현 가능하다.