La delegación es un patrón de diseño que consiste en que ciertas tareas, en vez de ser realizadas por el objeto son delegadas en ciertos objetos asistentes.
DelegateClass,
a la que se le pasa el nombre de la clase en la que se delega como parámetro (Flintstone en el ejemplo).
class Fred < DelegateClass(Flintstone)
def initialize
# ...
super(Flintstone.new(...))
end
# ...
end
Luego, en el initialize llamamos al de la superclase, pasandole como argumento el objeto en el que se delega.
Por ejemplo, podríamos reescribir la
práctica de los conjuntos
en la sección 14.6
delegando en la clase Array los métodos length
e include? (Puede encontar este fichero en
https://gist.github.com/crguezl/):
~/rubytesting/sets$ cat -n setsdelegate.rb
1 require 'delegate'
2 class Set2 < DelegateClass(Array)
3
4 attr_accessor :sep
5 attr_reader :a
6 protected :a
7
8 def initialize(a)
9 @sep = ', '
10 @a = a.uniq.sort
11 super(@a)
12 end
13
14 def to_s
15 @a.join(@sep)
16 end
17
18 # delegated
19 #def length
20 # @a.length
21 #end
22
23 alias cardinal length
24
25 # delegated
26 #def include?(x)
27 # @a.include? x
28 #end
29
30 end
31
32 if __FILE__ == $0
33 x = Set2.new [1, 2, 3, 3, 4]
34 puts "x = #{x}"
35 puts "x.length = #{x.length}" # x.length = 4
36 puts "x.cardinal = #{x.cardinal}" # x.cardinal = 4
37
38 puts "x includes 2 = #{x.include? 2}" # x includes 2 = true
39 puts "x includes 8 = #{x.include? 8}" # x includes 8 = false
40 end
En realidad DelegateClass(Array) es una llamada al método DelegateClass
del package delegate.
method_missing
method_missing redirecciona las llamadas al objeto en el que se
delega.
~/rubytesting/sets$ ruby setsdelegate.rb x = 1, 2, 3, 4 x.length = 4 x.cardinal = 4 x includes 2 = true x includes 8 = false
Otra forma de delegar es usar el método delegate de Rails.
Podemos instalar rails usando gem:
~$ sudo gem install rails Password: Successfully installed rails-3.1.1 1 gem installed Installing ri documentation for rails-3.1.1... file 'lib' not found Installing RDoc documentation for rails-3.1.1... file 'lib' not found ~$
El método delegate recibe la lista de nombres de los métodos (especificados como
símbolos o strings) a delegar
y el nombre del objeto atributo en el que se delega, especificado mediante
la clave :to.
Véase
https://gist.github.com/crguezl/.
~/rubytesting/TheRubyProgrammingLanguage/chapter8ReflectionandMetaprogramming$ cat -n delegation2.rb
1 require "rails"
2 module I
3 def f
4 puts "#{self.class}: doing f()"
5 end
6
7 def g
8 puts "#{self.class}: doing g()"
9 end
10 end
11
13 class A
14 include I
15 end
16
18 class B
19 include I
20 end
22
23 class C
24 attr_accessor :i
25 delegate :f, :g, :to => :i
26
27 def initialize(klass = A)
28 self.i = klass.new
29 end
30 end
32
33 c = C.new
34 c.f # output: A: doing f()
35 c.g # output: A: doing g()
36 c = C.new(B)
37 c.f # output: B: doing f()
38 c.g # output: B: doing g()
Casiano Rodriguez León 2015-01-07