¿Qué es "duck typing"?
Tal vez habrás notado que en Ruby no declaramos los tipos de las variables o métodos. To do es sólo un tipo de objeto. Los objetos Ruby (a diferencia de os objetos en otros lenguajes orientados a objetos) pueden ser modificados individualmente. Siempre puedes agregar métodos objeto por objeto. En Ruby, el comportamiento o capacidades de un objeto puede desviarse de aquellos definidos en su clase.
En Ruby, confiamos menos en el tipo (o clase) de un objeto y más en sus
capacidades. Entonces, Duck Typing significa que el tipo de un objeto
está definido por lo que puede hacer, no por lo que es. Duck Typing se
refiere a la tendencia de Ruby de preocuparse menos por la clase de un
objeto y más por los métodos que pueden ser llamados por el y las operaciones
que se pueden realizar con en el. En Ruby utilizaríamos el método
respond_to? o simplemente pasamos un objeto a un método y
sabemos que se generará una excepción si se utiliza inapropiadamente.
Si un objeto camina como un pato (walks like a duck) y habla como pato (talks like a duck), entonces el intérprete es feliz de tratarlo como si fuera un pato.
Considera el siguiente ejemplo:
1 # Verificar si el objeto defin el metodo to_str 2 puts 'Una cadena'.respond_to?(:to_str) 3 puts Exception.new.respond_to?(:to_str) 4 puts 4.respond_to?(:to_str)
El ejemplo anterior es el ejemplo más simple de la filosofía duc typing de Ruby: si un objeto grazna como pato (o actúa como una cadena), trátalo como a un pato (o una cadena). Cuando sea posible, debes tratar a un objeto de acuerdo a los métodos que define en vez de a la clase de la que hereda o los módulos que incluye.
Considera el siguiente ejemplo: p036pato.rb
1 class Pato 2 def grazna 3 'Quack!' 4 end 5 6 def nada 7 'Rema, rema, rema...' 8 end 9 end 10 11 class Ganso 12 def grazna 13 'Hock!' 14 end 15 16 def nada 17 'Splash splash splash...' 18 end 19 end 20 21 class GrabacionDePato 22 def grazna 23 play 24 end 25 26 def play 27 'Quack!' 28 end 29 end 30 31 def hazlo_graznar(pato) 32 pato.grazna 33 end 34 puts hazlo_graznar(Pato.new) 35 puts hazlo_graznar(GrabacionDePato.new) 36 37 def hazlo_nadar(pato) 38 pato.nada 39 end 40 puts hazlo_nadar(Pato.new) 41 puts hazlo_nadar(Ganso.new)
Observa el siguiente código:
1 def hazlo_graznar(pato) 2 pato.grazna 3 end 4 puts hazlo_graznar(Pato.new) 5 puts hazlo_graznar(GrabacionDePato.new)
Un método que le dice a un pato que grazne funciona cuando le pasas un objeto GrabacionDePato gracias al duck typing. De manera similar, en el siguiente código:
1 def hazlo_nadar(pato) 2 pato.nada 3 end 4 puts hazlo_nadar(Pato.new) 5 puts hazlo_nadar(Ganso.new)
Un método que le dice a un pato que nade, funciona para un ganso.