Duck typing

Nei linguaggi di programmazione orientati agli oggetti, il duck typing (lett. "tipizzazione ad anatra") si riferisce a uno stile di tipizzazione dinamica dove la semantica di un oggetto è determinata dall'insieme corrente dei suoi metodi e delle sue proprietà anziché dal fatto di estendere una particolare classe o implementare una specifica interfaccia. Il nome del concetto si riferisce al test dell'anatra attribuito a James Whitcomb Riley che può essere formulato come segue: «Quando vedo un uccello che cammina come un'anatra, nuota come un'anatra e starnazza come un'anatra, chiamo quell'uccello "anatra"».

Nel duck typing si è interessati solo agli aspetti di un oggetto che sono usati invece che al tipo dell'oggetto stesso. Per esempio in un linguaggio non duck-tipizzato si può creare una funzione che prende un oggetto di tipo Anatra (duck) e chiama i metodi starnazza (quack) e cammina (walk) di quell'oggetto. In un linguaggio duck-tipizzato, la funzione equivalente avrebbe preso un oggetto di qualunque tipo e chiamato i metodi walk e quack di quell'oggetto. Se quindi l'oggetto non ha i metodi chiamati, la funzione segnala un errore in run-time. È quest'azione di ogni oggetto avente i corretti metodi quack e walk che vengono accettati dalla funzione che evoca la citazione e quindi il nome di questa forma di tipizzazione.

Il duck typing è avvantaggiato abitualmente dal non dover testare per il tipo di argomento in metodi e corpi di funzione, basandosi sulla documentazione, codice pulito e prove per assicurare un uso corretto. Gli utenti che provengono da linguaggi tipizzati staticamente sono abitualmente tentati di aggiungere questo controllo statico dei tipi prima del run-time, reprimendo i benefici e la flessibilità del duck typing e vincolando il dinamismo del linguaggio.

Esempi del concetto[modifica | modifica wikitesto]

Si consideri il seguente pseudocodice per un linguaggio duck-tipizzato :

function calcola(a, b, c) => return (a+b)*c  esempio1 = calcola (1, 2, 3) esempio2 = calcola ([1, 2, 3], [4, 5, 6], 2) esempio3 = calcola ('mele ', 'e arance, ', 3)  print to_string esempio1 print to_string esempio2 print to_string esempio3 

In questo esempio ogni volta che viene chiamata la funzione calcola potrebbero essere usati oggetti non correlati fra loro (numeri, liste e stringhe). Fino a che l'oggetto supporta i metodi "+" e "*" l'operazione avrà successo. Se tradotto in Ruby o Python, per esempio, il risultato del codice sarà:

9 [1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6] mele e arance, mele e arance, mele e arance, 

Inoltre il duck typing permette il polimorfismo senza ereditarietà. Come unico requisito. la funzione calcola deve essere applicata a variabili aventi i metodi "+" e "*". Il duck test può essere visto nell'esempio seguente in Python. Dal punto di vista della funzione in_the_forest, l'oggetto è di tipo duck:

class Duck(object):     def quack(self):          print "Quaaaaaack!"     def feathers(self):          print "The duck has white and gray feathers."   class Person(object):     def quack(self):         print "The person imitates a duck."     def feathers(self):          print "The person takes a feather from the ground and shows it."  def in_the_forest(duck):     duck.quack()     duck.feathers()   def game():     donald = Duck()     john = Person()     in_the_forest(donald)     in_the_forest(john)  game() 

Il risultato sarà:

Quaaaaaack! The duck has white and gray feathers. The person imitates a duck. The person takes a feather from the ground and shows it. 

Duck typing in linguaggi tipizzati staticamente[modifica | modifica wikitesto]

Implementazioni[modifica | modifica wikitesto]

Si può avere un comportamento simile a quello di un linguaggio duck-tipizzato anche con linguaggi tipizzati.
I seguenti esempi ricalcano il comportamento del precedente scritto in Python.

JavaScript[modifica | modifica wikitesto]

var Duck = function(){     this.quack = function(){alert('Quaaaaaack!');};     this.feathers = function(){alert('The duck has white and gray feathers.');};     return this; };  var Person = function(){     this.quack = function(){alert('The person imitates a duck.');};     this.feathers = function(){alert('The person takes a feather from the ground and shows it.');};     this.name = function(){alert('John Smith');};     return this; };  var in_the_forest = function(duck){     duck.quack();     duck.feathers(); };  var game = function(){     var donald = new Duck;     var john = new Person;     in_the_forest(donald);     in_the_forest(john); };  game(); 

PHP[modifica | modifica wikitesto]

<?php class Duck{         function quack(){ echo "Quack\n";}         function fly(){ echo "Flap, Flap\n";} } class Person{         function __construct($name){$this->name=$name;}         function quack(){echo "{$this->name} walks in the forest and imitates ducks to draw them\n";}         function fly(){ echo "{$this->name} takes an airplane\n";} }  function QuackAndFly($obj){$obj->quack(); $obj->fly();}  QuackAndFly(new Duck()); QuackAndFly(new Person("Jules Verne")); ?> 
  Portale Informatica: accedi alle voci di Wikipedia che trattano di informatica