클래스 구현
클래스를 구현하거나 사용할 때 가장 중요한 것은 클래스의 경계를 구분 짓는 것이다. 휼륭한 클래스를 설계하기 위한 핵심은 어떤 부분을 외부에 공개하고 어떤 부분을 감출지를 결정하는 것이다.
클래스의 내부 외부 구분 이유
경계의 명확성이 객체의 자율성을 보장하기 때문 ➡ 프로그래머에게 구현의 자유 제공
자율적인 객체
객체 : 상태(state) + 행동(behavior) ➡️ 스스로 판단하고 행동하는 자율적인
존재
캡슐화 : 데이터와 기능을 객체 내부로 함께 묶는 것
핵심
스스로 상태 관리, 판단, 행동 ➡️ 자율적인 존재가 되기 위해선 외부의 간섭을 최소화 해야 한다. 외부의 개입을 최대한 차단 ➡️ 접근 제어가 필요한 이유
객체 = 퍼블릭 인터페이스 + 구현
객체의 상태는 숨기고, 행동만 외부에 공개해야함. 인터페이스의 구현과 분리가 객체지향의 핵심 원칙이다
협력
객체의 내부 상태는 외부에서 접근하지 못하도록 감추고, 퍼블릭 인터페이스를 통해 내부상태에 접근할 수 있도록 허용
➡️ 객체는 다른 객체의 인터페이스에 공개된 행동을 수행 하도록 요청(request)
할 수 있다. 요청을 받은 객체는 자율적인 방법에 따라 요청을 처리한 후 응답(response)
할 수 있다.
- 객체가 다른 객체와 상호작용할 수 있는 유일한 방법 ➡️
메시지 전송
➡️ 다른 객체에게 요청이 도착할 때, 해당 객체는메시지를 수신
했다고 표현
메서드
위와 같이 메시지를 수신한 객체는 스스로의 결정에 따라 자율적으로 메시지를 처리할 방법을 결정
➡️ 수신된 메시지를 처리하는 자신만의 방법이 메서드이다.
메서드와 메시지를 구분하는 것은 매우 중요
➡️ 다형성
상속과 다형성
Movie 내부에 할인 정책을 결정하는 조건문이 없는데도 불구하고, 어떻게 영화 요금을 계산할 때 할인 정책과 비율 할인 정책을 선택할 수 있을까?
➡ 상속과 다형성을 통해 특정 조건 선택적 실행 가능
컴파일 시간 의존성과 실행시간 의존성
의존성이란? 어떤 클래스가 다른 클래스에 접근할 수 있는 경로를 가지거나, 해당 클래스의 객체의 메서드를 호출할 경우 두 클래스 사이에 의존성이 존재
현재 Movie
클래스는 DiscountPolicy
와 의존성을 가지는데, 영화 요금 계산을 위해서는 DiscountPolicy
가 아닌 이를 상속받은 AmountDiscountPolicy
와 PercentDiscountPolicy
가 필요함
따라서 Movie의 ‘인스턴스’는 실행 시에 AmountDiscountPolicy
와 PercentDiscountPolicy
에 의존해야함
코드의 의존성과 런타임 시점에서의 의존성은 서로 다를 수 있다. 즉, 클래스 사이의 의존성과 객체 사이의 의존성은 동일하지 않을 수 있다. 또한 유연하고 쉽게 재사용 가능하며, 확장 가능한 객체지향은 코드의 의존성과 실행 시점의 의존성이 다르다.
하지만 설계가 유연해질 수록 코드를 이해하거나 디버깅 하는 것은 어렵다.
차이에 의한 프로그래밍
새로 추가하려는 클래스가 기존의 어떤 클래스와 매우 흡사하다면, 이 코드를 상속하여 재사용하는 것이 좋은 방법이다.
상속을 이용하면 클래스 사이에 관계를 설정하는 것만으로, 기존 클래스가 가진 모든 속성과 행동을 물려받을 수 있다.
이처럼 부모 클래스와 다른 부분만을 추가해서 새 클래스를 쉽고 빠르게 만드느 것이 차이에 의한 프로그래밍이다.
상속과 인터페이스
상속이 가치있는 이유는, 부모 클래스가 제공하는 모든 인터페이스를 자식 클래스가 물려받울 수 있기 때문이다. 인터페이스는 객체가 이해할 수 있는 메시지의 목록을 정의하는데, 상속을 통해 자식 클래스가 본인의 인터페이스에 부모의 인터페이스를 포함할 수 있게 되면서, 부모가 수신할 수 있는 모든 메시지를 수신 가능하기 때문에, 외부 객체는 자식 클래스와 부모 클래스를 동일한 타입으로 간주할 수 있다.
다형성
코드 상에서 Movie
클래스는 DiscountPolicy
클래스에게 메시지를 전송하지만, 실제로는 Movie와 협력하는 객체의 구현체가 무엇인지에 따라 다르다.
다형성이란 동일한 메시지를 수신했을 때 객체의 타입에 따라 다르게 응답할 수 있는 능력이다. 따라서 다형적인 협력에 참여하는 객체는 모든 같은 메시지를 이해할 수 있어야 하는데, 즉 인터페이스가 동일해야 한다.
다형성을 구현하는 방법은 매우 다양하지만, 메시지에 응답하기 위해 실행될 메서드를 컴파일 시점이 아니라 실행 시점에 결정한다 는 공통점이 있다. ➡️ 이를 지연 바인딩 혹은 동적 바인딩이라 부른다.
추상화와 유연성
추상화의 장점
- 추상화의 계층만 따로 떼어 놓고 살펴보면 요구사항의 정책을 높은 수준에서 서술할 수 있다.
- 추상화를 이용하면 설계가 좀 더 유연해진다.
추상화를 이용해 상위 정책을 기술하는 것은 기본적인 애플리케이션의 협력 흐름을 기술한다는 것을 의미한다. 재사용 가능한 설계의 기본을 이루는 디자인 패턴과 프레임워크 모두 추상화를 이용해 상위 정책을 정의하는 객체지향의 매커니즘을 활용한다.