예시 코드:
class Animal {
void eat() {
System.out.println("eating...");
}
}
class Dog extends Animal { // Dog IS-A Animal
void bark() {
System.out.println("barking...");
}
}
여기서 "Dog is an Animal"이라고 표현할 수 있습니다.
예시 코드:
class Engine {
void start() {
System.out.println("Engine starting...");
}
}
class Car { // Car HAS-A Engine
private Engine engine; // 컴포지션 관계
public Car() {
engine = new Engine();
}
void startCar() {
engine.start();
}
}
여기서 "Car has an Engine"이라고 표현할 수 있습니다.
주요 차이점:
사용 예시:
// IS-A 관계의 예시
class Vehicle {}
class Car extends Vehicle {} // Car IS-A Vehicle
class Bike extends Vehicle {} // Bike IS-A Vehicle
// HAS-A 관계의 예시
class Address {
String street;
String city;
}
class Student {
private Address address; // Student HAS-A Address
private String name;
public Student(String name, Address addr) {
this.name = name;
this.address = addr;
}
}
is-a와 has-a 관계 비교| 특징 | is-a 관계 (상속) | has-a 관계 (구성) |
|---|---|---|
| 관계의 의미 | 하위 클래스는 상위 클래스의 일종 | 한 클래스가 다른 클래스의 구성 요소를 포함 |
| 구현 방법 | 상속 (extends 키워드 사용) | 구성 (클래스 필드로 다른 클래스의 객체를 선언) |
| 목적 | 상위 클래스의 동작을 상속받아 재사용 및 확장 | 기능 분리 및 객체 협력을 통해 동작을 구현 |
| 클래스 간 결합도 | 결합도가 상대적으로 높음 | 결합도가 상대적으로 낮음 |
| 의존성 | 하위 클래스는 상위 클래스에 강하게 의존 | 구성된 클래스의 동작을 사용하지만 덜 의존적 |
| 사용 예 | Dog is a Animal, Car is a Vehicle | Car has a Engine, Computer has a Processor |
| 주로 사용되는 상황 | 클래스 계층에서 공통 동작을 상속받아 확장할 때 | 특정 클래스가 다른 클래스의 기능을 사용할 때 |
실제 사용시 고려사항:
1. IS-A 관계는 꼭 필요한 경우에만 사용해야 합니다 (상속의 오용을 피하기 위해)
2. HAS-A 관계는 더 유연한 설계가 가능하므로 상황에 따라 선호됩니다
3. "상속보다는 컴포지션을 사용하라"는 객체지향 설계 원칙을 고려해야 합니다