SimpleDelegator
SimpleDelegator
SimpleDelegator는 Delegator의 구체적인 구현 클래스예요. 생성자에 넘긴 객체로 모든 지원되는 메서드 호출을 위임하고, 나중에 __setobj__로 위임 대상 객체를 바꿀 수도 있어요.
출처: Ruby 3.3 API
본문
먼저 데코레이터 패턴의 예를 볼게요.
class User
def born_on
Date.new(1989, 9, 10)
end
end
require 'delegate'
class UserDecorator < SimpleDelegator
def birth_year
born_on.year
end
end
decorated_user = UserDecorator.new(User.new)
decorated_user.birth_year #=> 1989
decorated_user.__getobj__ #=> #<User: ...>
SimpleDelegator는 Delegator의 하위 클래스라는 점을 활용해, 위임 대상 객체에 메서드를 호출하고 싶을 때 super를 쓸 수 있어요.
class SuperArray < SimpleDelegator
def [](*args)
super + 1
end
end
SuperArray.new([1])[0] #=> 2
다음은 위임 대상 객체를 언제든 바꿀 수 있다는 점을 활용한 간단한 예시예요.
class Stats
def initialize
@source = SimpleDelegator.new([])
end
def stats(records)
@source.__setobj__(records)
"Elements: #{@source.size}\n" +
" Non-Nil: #{@source.compact.size}\n" +
" Unique: #{@source.uniq.size}\n"
end
end
s = Stats.new
puts s.stats(%w{James Edward Gray II})
puts
puts s.stats([1, 2, 3, nil, 4, 5, 1, 2])
출력은 다음과 같아요.
Elements: 4
Non-Nil: 4
Unique: 4
Elements: 8
Non-Nil: 7
Unique: 6
Public Instance Methods
__getobj__() { || ... }
현재 메서드 호출이 위임되는 객체를 돌려줘요.
__setobj__(obj)
위임 대상 객체를 obj로 바꿔요. SimpleDelegator의 메서드 자체가 바뀌는 건 아니니 주의해야 해요. 그래서 보통은 원래 위임 객체와 같은 타입의 객체로만 바꾸는 게 좋아요.
names = SimpleDelegator.new(%w{James Edward Gray II})
puts names[1] # => Edward
names.__setobj__(%w{Gavin Sinclair})
puts names[1] # => Sinclair