Reflection

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


La reflection, o introspezione, e’ la caratteristica di alcuni linguaggi di rendere disponibili al codice informazioni su se stesso. Detta cosi’ puo’ sembrare difficile, ma e’ molto semplice:
 >> puts 5.class
 Fixnum
Come vedete, e’ possibile effettuare una introspezione dell’oggetto 5, chiedendogli quale sia la sua classe. avremmo anche potuto chiedergli quale e’ la sua superclasse:
 >> 5.class.superclass
 >> Integer
 >> 5.class.superclass.superclass
 => Numeric
 >> 5.class.superclass.superclass.superclass
 => Object
Oppure sapere quali siano i suoi metodi:
 >> puts 5.methods.sort
 %
 &
 *
 **
 +
...e cosi’ via la lista e’ piuttosto lunga. Come potremmo fare per ridurla ?, Beh, alcuni metodi di reflection sono piu’ specifici. Infatti, abbiamo a disposizione:

Ovviamente alcuni di questi metodi sono disponibili solo per Classi e non per oggetti qualunque (si tratta di quelli in cui e’ presente la parola instance).

In piu’, questi metodi accettano un parametro opzionale, se e’ false verrannpo esclusi dall’elenco i metodi non definiti nella clase attuale. Anche questo sembra difficile ma non lo e’:
 >> class C
 >>  def met
 >>  end
 >> end
 => nil
 >> C.new.public_methods
 => ["dup", "hash", "private_methods", "nil?", "tainted?", "class", "singleton_me
 thods", "=~", "__send__", "untaint", "instance_eval", "extend", "kind_of?", "obj
 ect_id", "instance_variable_get", "inspect", "frozen?", "taint", "id", "public_m
 ethods", "respond_to?", "equal?", "to_a", "clone", "method", "protected_methods" 
 , "freeze", "instance_variable_set", "type", "is_a?", "methods", "==", "send", " 
 met", "instance_of?", "===", "instance_variables", "__id__", "eql?", "to_s", "di
 splay"]
 >> C.new.public_methods false
 => ["met"]
Ovviamente la reflection non si limita alla scoperta dei metodi. Possiamo ad esempio scoprire quali variabili sono state definite:

ci restituiscono degli array contenente i nomi delle variabili. In piu’:

permettono di leggere e modificare delle variabili specifiche. Per fare riferimento a variabile possiamo usare un simbolo o una stringa, indifferentemente. Ovviamente abbiamo a disposizione anche:

Questi metodi possono sembrare poco utili, ma sono invece fondamentali. Anzitutto permettono di manipolare un programma in maniera molto dinamica e semplice, e poi permettono di evitare tutta una serie di problemi relativi ad eval(). eval() e’, nella maggior parte dei casi, il male. Ma in altri linguaggi sarete costretti ad usare quella, se volete avere il valore di una variabile partendo dal nome. In ruby, per fortuna, potete evitarlo.

Il vero mostro della reflection e’, comunque, il modulo ObjectSpace

Updated on November 27, 2005 02:36 by Gabriele Renzi (151.42.223.101)