- 상속의 첫 번째 용도는 타입 계층을 구현하는 것이다.
- 상속의 두 번째 용도는 코드 재사용이다.
- 타입 계층을 목표로 상속을 사용하면 확장 가능하고 유연한 설계를 얻을 수 있다.
01 타입
개념 관점의 타입
- 객체들에 적용하는 개념이나 아이디어를 가리켜 타입
- 타입의 인스턴스 = 객체
- 타입의 구성 요소
- 심볼: 타입에 이름을 붙인 것
- 내연: 객체들이 가지는 공통적인 속성이나 행동
- 외연: 타입에 속하는 객체들의 집합
프로그래밍 언어 관점의 타입
- 타입은 비트 묶음에 의미를 부여하기 위해 정의된 제약과 규칙
- 타입에 수행될 수 있는 유효한 오퍼레이션의 집합을 정의한다.
- 타입에 수행되는 오퍼레이션에 대해 미리 약속된 문맥을 제공한다.
- 타입은 적용 가능한 오퍼레이션의 종류와 으미를 정의함으로써 코드의 의미를 명확하게 전달
객체지향 패러다임 관점의 타입
- 타입
- 공통의 특징을 공유하는 대상들의 분류
- 오퍼레이션을 적용할 수 있는 인스턴스들의 집합
- 객체의 타입이란 객체가 수신할 수 있는 메시지의 종류를 정의하는 것
- 객체가 수신샇 룻 있는 메시지의 집합 = 퍼블릭 인터페이스
- 객체에게 주용한 것은 행동이다!
02 타입 계층
타입 사이의 포함관계
- 포함하는 타입
- 외연 관점에서 더 크다
- 내연 관점에서 더 일반적 → 슈퍼타입
- 포함되는 타입
- 외연 관점에서는 더 작다
- 내연 관점에서는 더 특수하다 → 서브타입
- 내연 관점
- 일반화
- 타입의 정의를 좀 더 보편적이고 추상적으로 만드는 과정
- 특수화
- 좀 더 구체적이고 문맥 종속적으로 만드는 과정
- 외연 관점
객체지향 프로그래밍과 타입 계층
- 객체의 타입을 결정하는 것은 퍼블릭 인터페이스
- 서브타입의 인스턴스는 슈퍼타입의 인스턴스로 간주될 수 있다.
03 서브클래싱과 서브타이핑
언제 상속을 사용해야 하는가?
- 아래 조건을 모두 '예'라고 답할 수 있는 경우
- is-a 관계를 모델링
- 부모 클래스의 타입으로 자식 클래스를 사용해도 무방(행동 호환성)
is-a관계
행동 호환성
- 행동 호환성 여부를 판단하는 기준은 클라이언트의 관점
- 두 타입이 동일하게 행동할 것이라고 기대한다면 두 타입을 타입 계층으로 묶을 수 있다.
- instanceof의 사용
- 구체적인 클래스에 대한 결합도를 높이기 때문에 사용하지 않는 것이 좋다.
클라이언트의 기대에 따라 계층 분리하기
- 행동 호환성을 만족시키지 않는 상속 계층 → 클라이언트의 기대에 맞게 상속 계층을 분리하는 것이 해결 방법
- 인터페이스 분리 원칙
- 인터페이스 클라이언트의 기대에 따라 분리함으로써 변경에 의해 영향을 제어하는 설계
- 요구사항 속에서 클라이언트가 기대하는 행동에 집중해야 한다.
서브클래싱과 서브타이핑
- 서브 클래싱
- 코드를 재사용할 목적으로 상속을 사용하는 경우
- 자식 클래스의 인스턴스가 부모 클래스의 인스턴스를 대체할 수 없다.
- 서브 타이핑
- 타입 계층을 구성하기 위해 상속을 사용
- 자식 클래스의 인스턴스가 부모 클래스의 인스턴스를 대체할 수 있다.
04 리스코프 치환 원칙
- 서브타입은 그것의 기반 타입에 대해 대체 가능해야 한다.
클라이언트와 대체 가능성
- 상속 관계에 잇는 두 클래스 사이의 관계를 클라이언트와 떨어트려 놓고 판단하지 마라;
- 대체 가능성은 클라이언트에 의해 결정된다.
is-a 관계 다시 살펴보기
- is-a 관계는 객체지향에서 중요한 것은 객체의 속성이 아니라 객체의 행동이다.
리스코프 치환 원칙은 유연한 설계의 기반이다
- 클라이언트 입장에서 동일하게 행동하기만 한다면 클라이언트를 수정하지 않고도 상속 계층을 확장할 수 있다.
- 리스코프 치환 원칙을 준수해야만 서브타이핑 관계라고 말할 수 있다.
05 계약에 의한 설계와 서브타이핑
- 계약에 의한 설계
- 클라이언트와 서버 사이의 협력을 계약의 관점에서 표현하는 것
- 사전조건: 메서드를 실행하기 위해 만족시켜야 하는 조건
- 사후조건: 메서드가 실행된 후 서버가 클라이언트에 보장해야 하는 조건
- 클래스 불변식: 실행 전과 실행 후에 인스턴스가 만족시켜야 하는 것
서브타입과 계약
- 자식 클래스가 부모 클래스의 서브타입이 되기 위해서는...
- 서브타입에 더 강력한 사전조건을 정의할 수 없다.
- 서브타입에 슈퍼타입과 같거나 더 약한 사전 조건을 정의할 수 있다.
- 서브타입에 슈퍼타입과 같거나 더 강한 사후조건을 정의할 수 있다.
- 서브타입에 더 약한 사후조건을 정의할 수 없다.