💠 상속을 자제하고 합성(Composition)을 이용하자
상속과 합성 개념 정리 프로그래밍을 할때 가장 신경 써야 할 것 중 하나가 바로 코드 중복을 제거하여 재사용 함으로써 변경, 확장을 용이하게 만드는 것이다. 그런 관점에서 상속과 합성은 객
inpa.tistory.com
상속(Inheritance)
- 자식 클래스는 부모 클래스의 자원을 물려 받게 되며, 부모 클래스와 다른 부분만 추가하거나 재정의함으로서 기존 코드를 쉽게 확장할 수 있다.
- 상속 관계를 is-a 관계로 표현하기도 한다.
- 일반적인 클래스가 이미 구현이 되어 있는 상태에서 그보다 좀 더 구체적인 클래스를 구현하기 위해 사용되는 기법
- 상위 클래스의 코드를 하위 클래스가 재사용할 수 있다.
- 객체 주제는 같지만, 서로 다른 속성이나 기능들을 가지고 있을 때, 이러한 구조를 상속 관계를 통해 논리적으로 개념적으로 연관 시키는 것
- 명확한 is - a 관계에 있는 경우, 상위 클래스가 확장할 목적으로 설게되었고 문서화도 잘되어 있는 경우에 사용하면 좋다.
- 상속을 제대로 활용하기 위해서는 부모 클래스의 내부 구현에 대해 상세하게 알아야 하기 때문에 자식 클래스와 부모 클래스 사이의 결합도가 높아질 수 밖에 없다.
- 상속 관게는 컴파일 타임에 결정되고 고정되기 때문에 코드를 실행하는 도중에 변경할 수 없다.
- 여러 기능을 조합해야 하는 설계에 상속을 이용하게 된다면, 모든 조합별로 클래스를 하나하나 추가해주어야 한다. 이것을 클래스 폭발 문제라고 한다.
- Java8부터는 인터페이스의 디폴트 메서드 기능이 나오며서 인터페이스 내에서 로직 구현이 가능하여 상속의 장점이 약화되었다고 할 수 있다.
- 결과적으로 상속은 클래스 간의 관계를 한눈에 파악할 수 있고 코드를 재사용할 수 있는 쉽고 간단한 방법일지는 몰라도 우아한 방법이라고 할 수는 없다.
- 현업에서도 가능하면 상속을 지양하는 편이며, 클래스 상속을 해야할 때는 정말 개념적으로 연관 관계가 있을 때만 하는 상당히 제한적으로 선택적으로 다뤄진다.
- 상위 클래스에 결함이 있을 때 상속을 하게 되면, 부모 클래스의 결함도 자식 클래스에게 넘어오게 된다.
- 부모 클래스와 자식 클래스 사이의 개념적인 결합으로 인해, 부모 클래스를 변경할 때 자식 클래스도 함께 변경해야 하는 문제가 있다.
- 자식 클래스가 부모 클래스의 메서드를 오버라이딩할 때, 자식 클래스가 부모 클래스의 메서드 호출 방법에 영향을 받는 문제가 있다.
- 단일 상속의 한계
합성(조합, Compoision)
- 기존 클래스를 상속을 통한 확장하는 대신에, 필드로 클래스의 인스턴스를 참조하게 만드는 설계이다.
- 서로 관련없는 이질적인 클래스의 관계에서 한 클래스가 다른 클래스의 기능을 사용하여 구현해야 한다면, 합성의 방식을 사용한다고 보면 된다.
- 가령 학생이 수강하는 과목들이나, 자동차와 엔진 종류 간의 관계 같이 아주 연관이 없지는 않지만 상속 관계로 맺기에는 애매한 것들을 다루는 것으로 볼 수도 있다.
- 합성은 객체 간의 관계가 수직 관계가 아닌 수평 관계가 된다.
class Car(private val engine: Engine) {
fun drive() {
println("${engine.type} 엔진으로 드라이브~")
}
fun brakes() {
println("${engine.type} 엔진으로 브레이크~")
}
}
class Engine(val type: String) // 디젤, 가솔린, 전기
fun main() {
val dieselCar = Car(Engine("디젤"))
dieselCar.drive() // 디젤 엔진으로 드라이브~
val electricCar = Car(Engine("전기"))
electricCar.drive() // 전기 엔진으로 드라이브~
}
- 위의 초기화 코드에서 볼 수 있듯이, 마치 생성자에서 다른 클래스의 객체를 매개변수로 받는 형식으로 쓰여진다.
- 즉, Car 클래스가 Engine 클래스의 기능이 필요하다고 해서 무조건 상속하지 말고, 따로 클래스 인스턴스 변수에 저장하여 가져다 쓴다는 원리이다.
- 이 방식을 포워딩(forwarding)이라고 하며, 필드의 인스턴스를 참조해 사용하는 메서드를 포워딩 메서드(forwarding method)라고 부른다.
- 그래서 클래스 간의 합성 관계를 사용하는 데 다른 말로 Has-A 관계라고도 한다.
- 클래스 뿐만 아니라 추상 클래스, 인터페이스로도 가능하다.
- 합성을 이용하면 객체의 내부는 공개되지 않고 인터페이스를 통해 코드를 재사용하기 때문에, 구현에 대한 의존성을 인터페이스에 대한 의존성으로 변경하여 결합도를 낮출 수 있다.
'안드로이드 > etc.' 카테고리의 다른 글
[CS] 멀티 태스킹(Multi Tasking), 멀티 프로세싱(Multi Processing), 멀티 프로세스(Multi Process), 멀티 스레드(Multi Thread) (0) | 2024.12.12 |
---|---|
[CS] 비트(bit)와 바이트(byte), 음수 표현법 (0) | 2024.11.27 |
[CS] 블록체인(Blockchain) (0) | 2024.11.25 |