일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- 책을알려주는남자
- 채권
- 재테크
- 프로그래밍언어
- Java
- 독서
- C
- 독후감
- 경제
- 서평
- 투자
- 알고리즘트레이닝
- 알고리즘 공부
- JavaScript
- algorithmTest
- 책알남
- algorithmStudy
- 지혜를가진흑곰
- 자바
- 성분
- 주식
- 다독
- 돈
- 화장품
- 백준알고리즘
- 알고리즘공부
- C++
- algorithmtraining
- 프로그래머스 알고리즘 공부
- 자바스크립트
- Today
- Total
탁월함은 어떻게 나오는가?
IS-A(Inheritance, 상속) vs HAS-A(Composition, 포함) 관계 정리 본문
IS-A(Inheritance, 상속) vs HAS-A(Composition, 포함) 관계 정리
Snow-ball 2023. 6. 5. 17:35객체 지향 프로그래밍(Object-Oriented programming) 언어는 코드 재사용에 대한 이점이 있다.
코드 재사용 방법에는 상속 구현(inheritance, IS-A 관계) 또는 개체 구성(composition, HAS-A 관계) 두가지가 있다.
그러나 상속을 사용할 때는 컴파일러와 Java virtual machin(JVM)이 많은 일을 하지만, composition을 사용할 때는 상속의 기능을 사용할 수 있다.
IS-A Relationship
객체 지향 프로그래밍의 컨셉은 전부 IS-A을 기반으로 한 상속이며, 상속은 Class 상속과 Interface 상속 2가지 타입이 있다. 상속은 "A 타입은 B 타입의 것이다." 라고 하는 것이다. 예를들어 [ 사과는 과일이다. ] or [ 차는 차량이다. ] 과 같다. 그렇기 때문에 상속은 단방향이다. 예를 들자면 사과는 과일에 속하지만, 과일은 사과에 속하지 않기 때문이다.
이 부분에서 중요한 점은 우리는 아주 쉽게 IS-A relationship을 구별할 수 있다. 어디에서나 클래스 안에 extends 또는 implements 가 선언되어있고, 가지고 있다면 IS-A relationship이다.
HAS-A Relationship
Composition(HAS-A)는 개체 오브젝트를 인스턴스 변수로 참조하는 것을 의미한다.
예를들어 [ 마루티는 엔진을 가진다. ] or [ 집은 욕실을 가진다. ] 와 같다.
Car class 로 컨셉을 이해할 수 있다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
class Car {
private color: string;
private maxSpeed: number;
public carInfo(): void {
console.log(`Car Color= ${this.color} Max Speed= ${this.maxSpeed}`);
}
public setColor(color: string): void {
this.color = color;
}
public setMaxSpeed(maxSpeed: number): void {
this.maxSpeed = maxSpeed;
}
}
|
cs |
Car class 를 살펴보면, Car clas안에는 2개의 인스턴스 변수와 3개의 메소드가 존재한다.
마루티는 Car와 IS-A relationship 을 의미하는 Car class 로 확장하는 특정 유형의 자동차 타입니다.
1
2
3
4
5
6
7
8
|
class Maruti extends Car {
// 마루티 클래스는 extends Car 를 하면 Car class 로부터 모든 메소드를 상속받을 수 있다. (final 및 static 제외)
// 마루티는 또한 모든 특정 기능을 정의할 수 있다.
public MarutiStartDemo(): void {
const MarutiEngine = new Engine();
MarutiEngine.start();
}
}
|
cs |
마루티 클래스는 composition을 통해 엔진 클래스의 start() 메소드를 사용할 수 있다.
마루티 클래스와 엔진 클래스는 HAS-A relationship 이다.
1
2
3
4
5
6
7
8
9
|
class Engine {
public start(): void {
console.log("Engine Started:");
}
public stop(): void {
console.log("Engine Stopped:");
}
}
|
cs |
RelationsDemo class 는 Maruti class 개체를 만들고 초기화시킨다.
Maruti class 안에 setColor(), setMaxSpeed() 그리고 carInfo() 메소드를 가지고 있지 않지만 Maruti class는 Car class 와 IS-A relationship관계이기 때문에 사용할 수 있다.
1
2
3
4
5
6
7
8
9
|
class RelationsDemo {
public Demo(): void {
const myMaruti = new Maruti();
myMaruti.setColor("RED");
myMaruti.setMaxSpeed(180);
myMaruti.carInfo();
myMaruti.MarutiStartDemo();
}
}
|
cs |
아래는 출력 결과이다.
Composition(구성) 과 Inheritance(상속) 비교
- 클래스 composition 구성을 변경하는 것이 Inheritance 보다 쉽다. 그리고 슈퍼클래스의 변경은 하위 클래스에 대한 상속 계층에 영향을 준다.
- 상위 클래스에서 상속된 메서드와 메소드 이름은 같지만 반환 유형은 다른 메서드를 하위 클래스에 추가할 수 없다. Composition을 사용하면 백엔드 클래스에 영향없이 프론트엔드 클래스의 인터페이스를 변경할 수 있다.
- Composition은 동적 바인딩(run0time binding)이고 Inheritance는 정적 바인딩(compile time binding) 이다.
- 상속에는 다형성이 존재하기 때문에 새로운 프론트엔드 클래스(composition)을 추가하는 것보다 새로운 하위 클래스(inheritance)를 추가하는 것이 더 쉽다. 슈퍼클래스 인터페이스만 의존하는 코드가 있다면 해당 코드는 변경 없이 새로운 서브클래스와 함께 작동할 수 있다. 이것은 인터페이스와 함께 구성을 사용하지 않는 한 Composition에는 해당되지 않는다. Composition과 Interface를 함께 사용하면 매우 강력한 설계 도구가 된다.
- composition 과 inheritance 둘다 모든 클래스의 구현(인터페이스가 아니다)을 변경하는 것은 쉽다. 구현 변경의 파급 효과는 동일한 클래스 내에 남아 있다.
1. 코드 재사용을 위해서 inheritance를 사용하지 말아라!!
IS-A relationship 관계가 필요없으면서 코드만을 재사용하기 원한다면 composition 을 사용하라.
2. 다형성을 얻기 위해 상속을 사용하지 말아라!!
정말 원하는 것이 다형성이지만, 자연스러운 IS-A relationship이 없다면 interface를 사용하여 composition을 하라.
참조
* Inheritance (IS-A) vs, Composition(HAS-A) Relationship, w3resouce
'[Snow-ball]server > 객체지향' 카테고리의 다른 글
NestJS로 적용해보는 의존성 주입(dependency injection)과 일반 컴포지션 방식의 차이점에 대해 알아보자 (0) | 2023.08.10 |
---|---|
[SOLID] LSP(리스코브 치환의 원칙: Liskov Subsitution Principle) (0) | 2023.08.08 |
[SOLID] 의존관계 역전 원칙 (Dependency Inversion Principle) (0) | 2022.12.22 |