Mixin

Vedi tutte le pagine e le modifiche recenti o scarica i sorgenti nella pagina


I linguaggi ad oggetti sono basati su poche idee fondamentali, una delle quali è l’ereditarietà.

L’ereditarietà permette di riutilizzare codice scritto per una classe in una sottoclasse, e permette alcuni idiomi molto utili.

Alcuni linguaggi (python, C++, Lisp) forniscono un meccanismo detto Ereditarietà Multipla (in inglese Multiple Inheritance, o MI) in cui una classe può avere diverse superclassi. L’esempio classico, è quello di uno StudenteLavoratore che è sia uno studente sia un lavoratore.

In realtà questo è un cattivo esempio perché se Lavoratore e Studente discendono da Persona, ci si trova di fronte ad un caso abbastanza problematico di ereditarietà “a diamante” (immaginate una figura romboidale con le discendenze delle classi), cioè alcuni metodi o attributi vengono ereditati sia da una parte che dall’altra e quindi si deve procedere a rinominarli, ridefinirli etc etc

Poiché la MI può risultare in alcuni casi concettualmente complessa, alcuni linguaggi come Java, C# e Smalltalk forniscono solo l’Ereditarietà Singola (Single Inheritance, SI) cioè, la possibilità di avere al massimo una superclasse.

Così succede però che se la mia classe Cestino vuole fornire differenti interfacce devo ogni volta riscrivere i metodi per ognuna di esse, potendo ereditare solamente da una classe effettiva.

Ruby ed altri linguaggi forniscono un meccanismo che evita questi problemi, i Mixin.

Un Mixin in ruby si costruisce con un modulo, che può essere poi incluso in una classe in questo modo:

module M
 def foo
  "foo!" 
 end
end
class C
 include M
end
C.new.foo #=> "foo!" 

in questo modo possiamo fattorizzare delle funzionalità comuni in un modulo, e poi usarle in classi differenti senza problemi. Notate che è possibile programmare con i Mixin anche in tutti i linguaggi che supportano l’ereditarietà multipla, avendo cura di usare una classe in quei linguaggi solo come un contenitore di metodi e non come una vera classe.

Lo stile “Mixin-programming” è particolarmente utile quando un modulo fornisce un’insieme di funzionalità dipendenti da un’altra, in quanto è possibile definire nel mixin vari metodi in funzione di questa. Ad esempio

>> module Vendibile
>>  def stringa_prezzo
>>   prezzo.to_s+" euro" 
>>  end
>>  def prezzo_ivato
>>   prezzo+ (prezzo*20)/100
>>  end
>>  def to_s
>>   self.class.inspect+": "+stringa_prezzo
>>  end
>> end
=> nil
>> class Lampada
>>  include Vendibile
>>  def prezzo() 100 end
>> end
=> nil
>> l=Lampada.new
=> Lampada: 100 euro
>> l.prezzo_ivato
=> 120

Ruby fornisce alcuni Mixin molto carini nella libreria standard e nel core del linguaggio, tra cui il più usato è sicuramente Enumerable, che permette di aggiungere una ventina di utilissimi metodi ad una vostra classe con un paio di righe di codice. E’ per questo che in ruby praticamente tutto è Enumerable, stringhe, array, hash, struct file, directory, socket, documenti xml, yaml. etc etc. Un altro Mixin interessante è Comparable, che grazie ad un singolo metodo fornisce tutti gli opearori di comparazione.

Updated on December 06, 2005 09:15 by gls (151.38.187.128)