본문 바로가기

IT/오브젝트

ch11. 합성과 유연한 설계

04. 믹스인

상속을 사용한다면 다른 클래스를 간편하게 재사용하고 점진적으로 확장할 수 있지만 부모 클래스와 자식 클래스와 강하게 결합되기 떄문에 수정과 확장에 취약한 설계를 낳게 된다.

 

믹스인은 객체를 생성할 때 코드 일부를 클래스 안에 섞어 넣어 재사용하는 기법을 가르키는 용어다.

합성이 실행 시점에 객체를 조합하는 재사용 방법이라면 믹스인은 컴파일 시점에 필요한 코드조각을 조합하는 재사용 방법


기본 정책 구현하기

abstract class BasicRatePolicy {
def calculateFee(phone: Phone): Money =
phone.calls.map(calculateCallFee(_)).reduce(_ + _)
protected def calculateCallFee(call: Call): Money;
}

 

class RegularPolicy(val amount: Money, val seconds: Duration) extends BasicRatePolicy {
override protected def calculateCallFee(call: Call): Money =
amount * (call.duration.getSeconds / seconds.getSeconds)
}

트레이트로 부가 정책 구현하기

trait TaxablePolicy extends BasicRatePolicy {

def taxRate: Double

{ override def calculateFee(phone: Phone): Money

val fee = super.calculateFee(phone)

return fee + fee # taxRate } }

해당 코드는 BasicRatePolicy를 확장하는 트레이트이다. 이것은 상속의 개념이 아니라 TaxablePolicy가 BasicRatePolicy나 BasicRatePolicy의 자손에 해당하는 경우에만 믹스인이 가능하다.

 

TaxablePolicy는 BasicRatePolicy를 상속받은 경우에만 믹스인 될 수 있다. 다른 클래스나 트레이트에는 믹스인이 될 수 없다.

 

이사실은 믹스인과 상속의 가장 큰 차이점을 보여준다. 상속은 정적이지만 믹스인은 동적이다. 상속은 부모클래스와 자식 클래스의 관계를 코드를 작성하는 시점에 고정 시켜 버리지만 믹스인은 제약을 둘뿐 실제로 어떤 코드에 믹스인될 것인긴지를 결정하지 않는다.

 

따라서 TaxablePolicy에 super 호출로 실행되는 calculateFee 메서드를 보관한 코드는 실제로 트레이트가 믹스인되는 시점에 결정된다.

 

예를 들면 RegularPolicy에 믹스인되는 경우에는 RegularPolicy에 calcuateFee가 호출된다. 즉 컴파일 시점이 아닌 믹스인 되는 실행 시점에 결정된다고 생각하면된다. 


부가 정책 트레이트 믹스인하기

트레이트는 with을 이용하여 믹스인 한다. 이것을 트레이트 조합이라고 부른다

 

class TaxableRegularPolicy

amount: Money,

seconds: Duration,

val taxRate: Double). extends RegularPolicy (amount, seconds) with TaxablePolicy

이 객체의 인스턴스에 calculateFee 메세지를 전송했을 때 어떤 메서드가 실행될까? 스칼라는 특정 클래스에 믹스인한 클래스와 트레이트를 선형화해서 어떤 메서드를 호출할지 결정한다.

 

선형화 후의 TaxableRegularPolicy 계층 구조

 

선형화 구조를 만들기 위해서는 with에 선언 위치에 따라 달라진다.

class RateDiscountableAndTaxableRegularPolicy

amount: Money,

seconds: Duration,

val discountAmount: Money,

val taxRate: Double) extends Regular Policy (amount, seconds) with TaxablePolicy

with RateDiscountablePolicy

위의 코드에 대한 선형화 계층구조

또한 인스턴스를 생성할때 트레이트를 믹스인 할수도 있다.


쌓을 수 있는 변경

믹스인은 상속 계층 안에서 확장한 클래스보다 더 하위에 위치하게 된다. 다시 말해서 믹스인은 대상 클래스의 자식 클래스처럼 사용될 용도로 만들어지는 것이다. 따라서 믹스인을 추상 서브클래스 라고 부르기도 한다.

 

믹스인은 사용하면 클래스에 대한 변경 또는 확장을 독립적으로 구현한 후 필요한 시점에 차례대로 추가할 수 있다. 이러한 특징을 쌓을 수 있는 변경 이라고 부른다.

'IT > 오브젝트' 카테고리의 다른 글

ch.13 서브클래싱과 서브타이핑  (0) 2021.07.31
ch 12. 다형성  (0) 2021.07.24
ch.10 상속과 코드 재사용  (0) 2021.07.10
ch.09 유연한 설계  (0) 2021.07.03
DI(Dependency Injection) 와 IOC(inversion of control)  (0) 2021.04.18