29

Probably i am missing something simple, but i do not understand how to use Ruby's DelegateClass method, i mean when to use it instead of SimpleDelegator class. For example, all of the following seem to work mostly identically:

require 'delegate'

a = SimpleDelegator.new([0])
b = DelegateClass(Array).new([0])
c = DelegateClass(String).new([0])
a << 1
b << 2
c << 3
p a # => [0, 1]
p b # => [0, 2]
p c # => [0, 3]

Note that it does not seem to matter which class is passed to DelegateClass.

Alexey
  • 3,843
  • 6
  • 30
  • 44
  • 1
    After thinking about it for some time, the whole Delegator Pattern looks to me like a quick dirty hack :). You send a message, and you do not know which class will be responsible for answering. The delegator passes through all the messages it does not recognize without knowing if and how they will be answered (otherwise it could be realised as a subclass, or use composition, couldn't it?). The original class does not really control anything anymore and does not even know there is a delegator between it and the rest of the world. – Alexey Jun 20 '13 at 07:57

1 Answers1

22

Use subclass SimpleDelegator when you want an object that both has its own behavior and delegates to different objects during its lifetime.

Essentially saying use DelegateClass when the class you are creating is not going to get a different object. TempFile in Ruby is only going to decorate a File object SimpleDelegator can be reused on different objects.

Example:

require 'delegate'


class TicketSeller
  def sellTicket()
    'Here is a ticket'
  end
end


class NoTicketSeller
  def sellTicket()
    'Sorry-come back tomorrow'
  end
end


class TicketOffice < SimpleDelegator
  def initialize
    @seller = TicketSeller.new
    @noseller = NoTicketSeller.new
    super(@seller)
  end
  def allowSales(allow = true)
    __setobj__(allow ? @seller : @noseller)
    allow
  end
end

to = TicketOffice.new
to.sellTicket   »   "Here is a ticket"
to.allowSales(false)    »   false
to.sellTicket   »   "Sorry-come back tomorrow"
to.allowSales(true)     »   true
to.sellTicket   »   "Here is a ticket"

Here is another good explanation a-delegate-matter

jtzero
  • 2,204
  • 2
  • 25
  • 44
  • 4
    You shouldn't reuse a `SimpleDelegator` for different *types* of objects, though it's ok to reuse for different *instances*; [the docs](http://ruby-doc.org/stdlib-2.1.0/libdoc/delegate/rdoc/SimpleDelegator.html#__setobj__-method) explicitly say about `#__setobj__`: "It’s important to note that this does not cause SimpleDelegator’s methods to change. ... you probably only want to change delegation to objects of the same type as the original delegate." – nickgrim Feb 02 '15 at 13:11