Duck Typing

Talvez você já tenha notado, que em Ruby não declaramos os tipos de variáveis ou métodos – tudo já é algum tipo de um objeto. Objetos em Ruby (ao contrário dos objetos em outras linguagens orientadas a objeto) podem ser individualmente modificados. Você sempre pode adicionar métodos em um objeto. Em Ruby, o comportamento ou a capacidade de um objeto, pode se diferenciar dos fornecidos pela sua classe.

Em Ruby, nós confiamos menos no tipo (ou classe) de um objeto e mais nas suas capacidades. Por isso, Duck Typing (que por ser um termo técnico, não há uma tradução precisa), significa que um tipo de objeto é definido por aquilo que ele pode fazer, não pelo que ele é. Duck Typing refere-se a tendência de Ruby estar menos preocupado com a classe de um objeto e mais preocupado com quais os métodos que podem ser chamados e quais operações podem ser executadas sobre ele. Em Ruby, usaríamos respond_to? ou poderíamos, simplesmente passar um objeto para um método e saberíamos que uma exceção seria levantada, se formos utilizar de forma inadequada.

Se um objeto anda como um pato e fala como um pato, então o interpretador Ruby está feliz em tratá-lo como se fosse um pato.

Considere o seguinte exemplo.

1   # Verificar se o objeto defini o método to_str
2   puts ('Uma string'.respond_to? :to_str) # => true
3   puts (Exception.new.respond_to? :to_str) # => false
4   puts (4.respond_to? :to_str) # => false

O exemplo acima é o exemplo mais simples da filosofia Ruby de Duck Typing: se um objeto faz “quack” como um pato (ou age como uma string), basta ir em frente e tratá-lo como um pato (ou uma string). Sempre que possível, você deve tratar objetos de acordo com os métodos que ele possui, ao invés, de definir as classes a partir do que eles herdam ou módulos que incluem.

Agora, considere as três seguintes classes – Pato, Ganso e PatoDonald. Programa p036duck.rb

Código

 1   class Pato
 2     def quack
 3       'Quack!'
 4     end
 5 
 6     def nadar
 7       'nadando nadando nadando...'
 8     end
 9   end
10 
11   class Ganso
12     def grasnar
13       'Grasnando!'
14     end
15 
16     def nadar
17       'Splash splash splash...'
18     end
19   end
20 
21   class PatoDonald
22     def quack
23       play
24     end
25 
26     def play
27       'Quack! Sou o Pato Donald!'
28     end
29   end
30 
31   def faz_quack(pato)
32     pato.quack
33   end
34   puts faz_quack(Pato.new)
35   puts faz_quack(PatoDonald.new)
36 
37   def faz_nadar(duck)
38     duck.nadar
39   end
40   puts faz_nadar(Pato.new)
41   puts faz_nadar(Ganso.new)

Se você consultar o código abaixo:

1   def faz_quack(pato)
2     pato.quack
3   end
4   puts faz_quack(Pato.new)
5   puts faz_quack(PatoDonald.new)

Um método que disse a um Pato para fazer quack funciona quando recebe um PatoDonald, graças ao Duck Typing. O mesmo pode ser observado no seguinte código:

1   def faz_nadar(pato)
2     pato.nadar
3   end
4   puts faz_nadar(Pato.new)
5   puts faz_nadar(Ganso.new)

Quando um método que diz para um Pato nadar recebe um Ganso, ele funciona.

Logo do Guru-SP

Este material tem como base o tutorial do RubyLearning.com de Satish Talim e foi traduzido por membros do GURU-SP com a permissão do autor.

Ajude o RubyLearning participando em algum dos cursos pagos ou fazendo uma doação para o projeto

Voltar para o índice