SimpleDelegator 클래스
SimpleDelegator 클래스
SimpleDelegator는 Delegator의 구체적인 구현이에요. 생성자에 넘긴 객체로 지원되는 모든 메서드 호출을 위임(delegate)하고, 나중에 __setobj__로 위임 대상을 바꿀 수도 있죠.
출처: Ruby 4.0 API
본문
이 클래스는 그냥 객체를 감싸서(decorate) 메서드 호출을 전부 원본 객체로 넘겨주고 싶을 때 써요. 다음 예시를 볼게요.
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: ...>
UserDecorator.new(User.new)에서 넘긴 User 객체가 내부 위임 대상이 돼요. born_on 같은 메서드는 정의하지 않아도 SimpleDelegator가 원본 객체로 전달해 주죠.
SimpleDelegator가 Delegator의 하위 클래스라는 점을 이용하면, super를 호출해서 위임 대상 객체에서 메서드를 실행시킬 수도 있어요.
class SuperArray < SimpleDelegator
def [](*args)
super + 1
end
end
SuperArray.new([1])[0] #=> 2
[]에서 super를 부르면 위임 대상인 실제 배열의 []가 실행되고, 그 결과에 1을 더해 반환한 거예요.
위임 대상을 아무 때나 바꿀 수 있다는 점을 활용한 예시도 볼게요.
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])
Prints:
Elements: 4
Non-Nil: 4
Unique: 4
Elements: 8
Non-Nil: 7
Unique: 6
@source가 가리키는 SimpleDelegator에 매번 다른 레코드 배열을 __setobj__로 넣어 주고, 그 위에서 size, compact, uniq를 호출하는 방식이에요.
Public Instance Methods
getobj → object
현재 메서드 호출이 위임되고 있는 객체를 반환해요.
setobj(obj) → obj
위임 대상을 obj로 바꿔요.
중요한 점은 이 변경이 SimpleDelegator 자신의 메서드에는 영향을 주지 않는다는 거예요. 그래서 위임 대상을 바꿀 때는 원래 위임 대상과 같은 타입의 객체로 바꾸는 게 보통 좋아요.
위임 대상을 바꾸는 예시를 볼게요.
names = SimpleDelegator.new(%w{James Edward Gray II})
puts names[1] # => Edward
names.__setobj__(%w{Gavin Sinclair})
puts names[1] # => Sinclair
names[1]이 처음엔 Edward, __setobj__ 후에는 Sinclair를 반환하는 걸 볼 수 있어요.