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 # ... endLuego, 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 endEn 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