반응형
Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
Tags
- 자바
- 코루틴
- 알게되는
- 커스텀상태
- theming
- 안드로이드스튜디오
- viewmodel
- Kotlin
- g 단위테스트
- 디자인패턴
- k8s
- 안드로이드
- Gradle
- 알고리즘
- 회고
- 병럴프로그래밍
- 책
- mockito
- ReactiveProgramming
- 병렬프로그래밍
- Rxjava
- 글또
- 테스트
- Compose
- kotlin강좌
- Coroutine
- android
- 코틀린
- 스레드
- 안드로이드강좌
Archives
- Today
- Total
선생님, 개발을 잘하고 싶어요.
[오브젝트] 챕터 13 - 서브클래싱과 서브타이핑 본문
단순히 코드 재사용을 위한 상속에 서브클래싱이라는 이름을 붙히고 타입 계층을 만들기 위해서 사용하는 상속에 서브타이핑이라는 이름이 있다는 사실을 알게된 챕터입니다.
이런 구분을 알게 되니까 LSP의 진정한 의미에 대해서 조금은 알게된 것 같습니다. 원래는 “당연히 부모 타입에 자식 타입 인스턴스를 넣고 사용할 수 있는데 뭔 소리야?”라고 생각하고 대수롭지 않게 여긴 설계 원칙이였는데요. 이번 챕터를 통해서 객체 지향 설계의 정수가 아닌가? 라는 생각이 들게 되었습니다.
우선 LSP와 다형성의 관계가 매우 재밌었습니다. 객체 지향을 처음 배울 때 부터 우리는 다형성에 대해서 배웠습니다만 다형성을 단순히 Overloading 정도로 생각하고 있었던 것 같아요.
타입이라는 개념으로 역할을 정의하고, 코드를 OCP하게 만들기 위해서는 LSP가 반드시 지켜져야 한다는 사실을 알게되었습니다. 타입 계층을 만들려면, 무조건 구체적인 타입이 일반적인 타입의 인스턴스로 활용될 수 있어야 한다는 생각을 하게 되었네요.
- 도입타입 계층안 에서 부모 클래스는 일반적인 개념을 나타내고 자식 클래스는 특수한 개념을 나타낸다. 부모는 자식의 일반화이고 자식은 부모의 특수화라고 생각할 수 있다.따라서 우리가 상속을 사용하는 목표는 타입 계층을 구현하는 것이 되어야 한다. 다른 말로 하면 다형적인 객체를 구현하기 위해서 객체의 행동을 기반으로 타입 계층을 구성해야 한다는 것이다.</aside>
- <aside> 💡 이번 장에서는 올바른 타입 계층을 구성하는 원칙을 알아보고자 한다.
- 상속을 사용하면 간단하게 자식 클래스에서 부모 클래스의 코드를 재사용할 수 있다 하지만 단순히 이런 용도로 상속을 사용하면 자식 클래스와 부모 클래스 간의 강한 결합도로 인해서 변경하기 어려운 코드가 만들어진다.
- 상속은 두 가지 목적으로 사용된다. 하나는 타입 계층을 구현하는 것이고 나머지 하나는 코드 재사용이다.
- 타입
- 개념 관점의 타입
- 심볼: 타입의 이름
- 내연: 타입이 가진 속성과 행동 집합
- 외연: 타입에 속하는 객체 집합
- 프로그래밍 언어적 관점의 타입
- 비트 묶음에 의미를 부여하기 위해 정의된 제약과 규칙
- 타입에 수행될 수 있는 유효 오퍼레이터 정의
- 타입에 수행되는 오퍼레이션에 대해 미리 약속된 문맥 제공
- 타입은 적용 가능한 오퍼레이션 종류와 의미를 정의
- 객체지향 패러다임 관점의 타입
- 객체의 퍼블릭 인터페이스를 정의하는 것
- 타입을 결정하는 건 객체가 외부에 제공하는 행동
- </aside>
- 개념 관점의 타입
- 타입 계층
- 타입 사이 포함관계
- 구체적인 타입은 일반적인 타입의 부분 집합이다. (타입은 일반화 - 특수화 관계를 가진다.)
- 슈퍼타입: 일반적인 타입
- 서브타입: 특수한 타입
- 특수한 타입에 속한 인스턴스는 동시에 더 일반적인 타입의 인스턴스이기도 하다. (업캐스팅)
- </aside>
- 객체지향 프로그래밍과 타입 계층
- 서브타입의 인스턴스는 슈퍼타입의 인스턴스로 간주될 수 있다.
- 상속 + 다형성의 관계를 이해하기 위한 시작점
- 타입 사이 포함관계
- 서브클래싱과 서브타이핑
- 상속은 is-a 관계일 때 사용하라는 격언은 어휘적으로 낚시다.
- 정사각형은 직사각형인가? (Square extends Rectangle)? 유명한 오류
- 클라이언트 입장에서 부모 클래스의 타입으로 자식 클래스를 사용해도 무방한가? 가 핵심이다!
- 행동 호환성이라고 한다.
- 행동의 호환을 판단하는 기준은 항상 클라이언트 관점이다.
- 클라이언트의 기대에 따라 계층 분리하기
- 클라이언트 기대에 맞게 상속 계층을 분리하라.
- 클라이언트에 따라 인터페이스를 분리하라.
- 인터페이스는 클라이언트가 기대하는 바에 따라 분리돼야 한다.
- 인터페이스라는 건 대부분 클라이언트의 요구가 바뀌면서 변경된다.
- 이 처럼 클라이언트의 기대에 따라 인터페이스를 분리하여 변경에 의한 영향을 제어하는 설계 원칙을 인터페이스 분리 원칙이라고 한다(ISP)
- 요구사항 속에서 클라이언트가 기대하는 행동에 집중하라는 것이다.
- 서브클래싱: 코드 재사용 목적을 상속 활용 - 구현 상속, 클래스 상속
- 서브타이핑: 타입 계층을 구성하기 위해 상속 활용 - 인터페이스 상속
- 상속은 is-a 관계일 때 사용하라는 격언은 어휘적으로 낚시다.
- </aside>
- 리스코프 치환 원칙 (LSP)</aside>
- 부모 클래스를 대체할 수 있도록 구현된 상속 관계만을 서브타이핑이라 함
- 이를 만족하기 위해서는
- 부모 클래스에 대한 클라이언트의 가정을 자식 클래스가 준수해야함 을 의미한다.
- 모델의 유효성은 클라이언트 관점에서만 검증 가능
- 대체 가능성을 결정하는 건 클라이언트다.
- LSP를 지키면
- 클라이언트가 어떤 자식 클래스와도 안정적으로 협력할 수 있는 상속 구조를 구현할 수 있는 가이드라인 제공
- 유연할뿐만 아니라 확장성 높다.
- LSP 위반은 잠재적 OCP 위반이다.
- 클라이언트 관점에서 서로 다른 구성 요소를 동일하게 다뤄야 한다면? → LSP 원칙을 떠올리자.
- <aside> 💡 서브타입은 그것의 기반 타입에 대해 대체 가능해야 한다.
- 계약에 의한 설계와 서브타이핑
- 부모 클래스에 적용된 계약
- 사전조건 (precondition)
- 사후조건 (postcondition)
- 클래스 불변식 (class invariant)
- 자식 클래스를 만들려면 부모 클래스 - 클라이언트간 약속을 깨지 않아야 한다.
- 부모와 같거나 보다 약한 사전조건
- 부모와 같거나 보다 강한 사후조건
- 부모 클래스에 적용된 계약
'일상 > 책 리뷰' 카테고리의 다른 글
[오브젝트] 챕터 15 - 디자인 패턴과 프레임워크 (0) | 2022.03.23 |
---|---|
[오브젝트] 챕터 14 - 일관성 있는 협력 (0) | 2022.03.23 |
[오브젝트] 챕터 12 - 다형성 (0) | 2022.03.23 |
[오브젝트] 챕터 11 - 합성과 유연한 설계 (0) | 2022.03.20 |
[오브젝트] 챕터 10 - 상속과 코드 재사용 (0) | 2022.03.19 |
Comments