p.62
Movie
생성자에서 인자의 타입이DiscountPolicy
임에도AmountDiscountPolicy
와PercentDiscountPolicy
의 인스턴스를 전달할 수 있는 이유가 바로 이 때문이다.
또한DiscountPolicy
타입인Movie
의 인스턴스 변수인discountPolicy
에 인자로 전달된AmountDiscountPolicy
나PercentDiscountPolicy
의 인스턴스를 할당할 수 있는 이유도 이 때문이다.
이 문단이 명확하지 않아서 나름대로의 해석을 해보았는데, 아마도 아닌 것 같다. 조영호님이 사용하는 전달이라는 단어와 할당이라는 단어, 그리고 전송이라는 단어의 차이를 명확하게 인지하지 못했기 때문이다.
저자는 상속과 인터페이스를 설명하며 자식 클래스가 부모 클래스를 대체하는 두 가지 경우를 설명하였다.
1. 생성자에서 인자의 타입은 DiscountPolicy
이지만, this.discounPolicy
에는 AmountDiscountPolicy
가 들어갈 것이다. (할당)
public class Movie{
public Movie(String title, Duration runningTime, Money fee, DiscountPolicy discountPolicy){
...
this.discountPolicy = discountPolicy;
}
}
discountPolicy.calculateDiscountAmount
public class Movie {
public Money calculateMovieFee(Screening screening) {
return fee.minus(discountPolicy.calculateDiscountAmount(screening));
}
}
그러나 종종 구현은 공유할 필요가 없고 순수하게 인터페이스만 공유하고 싶을 때가 있다. ... 추상 클래스를 이용해 다형성을 구현했던 할인 정책과 달리 할인 조건은 구현을 공유할 필요가 없기 때문에 그림 2.12과 같이 자바의 인터페이스를 이용해 타입 계층을 구현했다.
DiscountCondition
인터페이스를 실체화하고 있는 SequenceCondition과 PeriodCondition은 동일한 인터페이스르 공유하며 다형적인 협력에 참여할 수 있다.
사실 추상 클래스와 인터페이스의 차이가 명확히 이해되지 않는다. 파이썬을 사용하는 나로써는 더욱 미묘한 것 같다. 하지만 명확하게 구분되어 있는 부분은 구현을 공유할 것이냐 아니냐는 점이다. 실제로 이 책의 예시에서도 자식 클래스는 부모 클래스의 많은 부분을 공유하므로 중복된 코드를 작성할 필요가 없다. 그런데 만약 구현을 공유하지 않을 때에도 추상클래스를 써도 되는 것이라면 사실 추상클래스 하나면 되지 않을까 싶긴 하다. 그러니까 추상클래스는 인터페이스를 포함하고 인터페이스라는 개념은 필요 없지 않은가 하는 점이다.
합성은 상속이 가지는 두 가지 문제를 모두 해결한다. 인터페이스에 정의된 메시지를 통해서만 재사용이 가능하기 때문에 구현을 효과적으로 캡슐화할 수 있다.
여기서 캡슐화는 구현 내부를 몰라도 된다는 의미일 것이다. (상속과 다르게)
객체 지향이란 객체를 지향하는 것이다. 따라서 객체지향 패러다임의 중심에는 객체가 위치한다. 그러나 각 객체를 따로 떼어놓고 이야기하는 것은 무의미하다. 객체지향에서 가장 중요한 것은 애플리케이션의 기능을 구현하기 위해 협력에 참여하는 객체들 사이의 상호작용이다. 객체들은 협력에 참여하기 위해 역할을 부여받고 역할에 적합한 책임을 수행한다.