✌️ Chapter 6: 상속을 이용해 새로운 행동 얻기
📚 고전적 상속 이해하기
- 상속이란 자동화된 메시지 전달시스템이다.
- 상속 시스템은 객체가 이해하지 못한 메시지를 어디로 전달해야 하는지를 정의한다. 특정 객체가 이해할 수 없는 메시지를 전달받았을 경우 그 객체는 이 메시지를 다른 객체에게 전달한다. 이런 전달의 관계를 만드는 것이 상속이다.
- 고전적인 상속 관계는 하위클래스(subclasses)를 만드는 것을 통해 정의된다. 메시지는 하위클래스에서 상위클래스로 전달된다.
📚 상속을 사용해야 하는 지점을 알기
🎈 구체 클래스에서 시작하기
- 예를 들어본다.
- 아래 코드는 Bicycle 클래스고 모든 로드 자전거는 이 클래스의 인스턴스이다.
class Bicycle
attr_reader :size, :tape_color
def initialize(args)
@size = args[:size]
@tape_color = args[:tape_color]
end
# 모든 자전거가 동일한 크기의 타이어와 체인을 기본값으로 갖는다.
def spares
{
chain: '10-speed',
tire_size: '23',
tape_color: tape_color
}
end
# 다른 메서드들..
end
bike = Bicycle.new(
size: 'M',
tape_color: 'red'
)
bike.size # M
bike.spares
# { :tire_size => '23', :chain => '10-speed' :tape_color => 'red'}
- 이 클래스에서 요구사항이 들어왔다. 디자인의 목표는 마운틴 자전거를 지원하도록 하는 것이다.
- 마운틴 자전거에는 서스펜션이 필요하다.
🎈 자전거 종류 추가하기
- 아래 코드의
spares
메서드에if
문을 포함하게 되었다. 이 예시는 안티패턴을 보여주기 위한 간단한 우회로에 불과하다. (문제가 많은 패턴)
class Bicycle
attr_reader :style, :size, :tape_color,
:front_shock, :rear_shock
def initialize(args)
@type = args[:style]
@size = args[:size]
@tape_color = args[:tape_color]
@front_shock = args[:front_shock]
@rear_shock = args[:rear_shock]
end
# 좋지 않다.
def spares
if style == :road
{
chain: '10-speed',
tire_size: '23',
tape_color: tape_color
}
else
chain: '10-speed',
tire_size: '2.1',
rear_shock: rear_shock
end
end
end
bike = Bicycle.new(
style: :mountain,
size: 'S',
front_shock: 'Manitou',
rear_shock: 'Fox'
)
bike.spares
# {:tire_size => "2.1", :chain => "10-speed", :rear_shock => 'Fox'}
- 위 코드는
style
변수가 가지고 있는 값을 확인하고 어떤 예비부품이 필요한지 결정한다. - 이렇게 코드를 구성하면 새로운
style
을 추가하는 경우if
문을 수정해야 한다. - 또한,
spares
메서드는 기본 문자열을 가지고 있는데, 이 문자열 중 몇몇은if
문의 조건마다 반복되고 있다. Bicycle
은 하나 이상의 책임을 지고 있으며 수정요쳥에 노출되기 쉬운 코드를 품고 있으며 그 자체로는 재사용이 불가능하다.- 이 코드는 자기가 어떤 종류인지 알고 있는 어트리뷰트를 확인하는
if
문을 포함하고 있다. 이 어트리뷰트를 통해 자기 자신에게 어떤 메시지를 보낼지 결정한다. - 오리 타입에서는 객체의 클래스를 확인하고 이 객체에게 어떤 메시지를 전송할지 결정하는
if
문이 있었다. - 송신자의 입장에서는 "나는 네가 누구인지 알고 있다. 때문에 네가 무엇을 하는지도 안다." 이런 지식은 수정 비용을 높이는 의존성이다.