CosaRuby intendiamoè perpieno pseudokeyword?
Tuttidi pseudokeyword, cioè di quelle parole che in qualche modo sembrano far parte della sintassi,
e che spesso in altri linguaggi sono appunto delle keyword, ma che in ruby
sono semplicemente dei metodi.
attr() e gli altri:
class C attr_accessor :var endIn realta’
attr_accessor e’ un normalisimo metodo, che prende in input un simbolo e tramite eval() definisce altri metodi. Questo metodo assomiglia ad una keyword perche’
* funziona in modo dichiarativo
* non usa parentesi
Puo’ sembrare stupido ma la differenza tra molte keyword e dei normali metodi e’ nel loro aspetto dichiarativo.
Cosa si intende per dichiarativo? Semplicemente che ci si limita a indicare cosa di desidera, senza curarsi dipublic void mio_metodo(){...
Noi non sappiamo, ne ci interessa, il meccanismo per cui mio_metodo() diventa privato. Ci limitiamo a dichiararlo tale, e java si occupa dei dettagli.
class C def foo end private :foo endQuesto e’ ancora un metodo “classico”, altri usi lo rendono ancora piu’ simile ad una keyword:
class C private def privatissimo ... end public def metodo ... end protected def protetto ... end end
public/private/protected sembrano delle keyword, ma in realta’ non lo sono affatto!
Non dimenticate, infatti, che la dichiarazione di una classe (o di un modulo) in ruby e’ semplicemente un altro pezzetto di codice che viene eseguito come tutto il resto.
Infatti possiamo avere anche questo:
>> class C >> puts self >> end C => nilDunque,
public/private/protected sono in realta’ dei normali metodi.
Ma come funzionano?
Beh, dicono a ruby di trattare ogni definizione di un metodo che li segue in una certa maniera.
A come fanno a sapere quando un metodo viene definito?
Facile, usano method_added()
Questo metodo viene chiamato ogni volta che viene definito un metodo, e gli viene passato il nome del metodo stesso. Un esempio banale:
>> class Class >> def method_added(id) >> puts 'aggiunto il metodo %s' % id >> end >> end aggiunto il metodo method_added => nilNotate come
method_added() sia stato chiamato subito dopo essere stato definito :)
Andando avanti:
>> class C >> def foo >> end >> end aggiunto il metodo foo => nilChiaro il concetto?
A questo punto possiamo provare a definire una pseudo keyword anche noi.
La pseudo keyword ci permettera di dichiarare dei metodi come metodi di test (non che la cosa sia molto utile, perche’ il modulo Test::Unit fa gia’ molte piu’ cose e meglio.
class Esempio Test 'Test 0. vuoto' def foo end def metodo # non un test end Test 'Test 1. This test will fail' def this_fail assert 10 < 5; end Test "Test 2. This test will pass", :this_pass def this_pass assert 10 > 5 end end run_tests(Esempio)E ci aspettiamo un output del genere:
Test 0. vuoto: true Test 1. This test will fail: false Test 2. This test will pass: trueAnzitutto definiamo un metodo
assert (potremmo anche usare quelle definite in Test::Unit::Assertion ):
def assert(condition) raise 'assertion failed!!' if not condition true endNotate che anche
assert e’ una keyword in altri linguaggi :)
Ora definiamo un meccanismo semplice per associare una descrizione ad un metodo:
def Test(descr) @is_test=desc endIn questo modo, quando useremo
Test() potremo avere l’informazione contenente la descrizione disponibile.
Ora definiamo method_added():
class Class def method_added(id) UT[id]=desc if @is_test @is_test=false end endCosa significa quell’UT ? Semplice, salviamo la descrizione riguardo il metodo in un
Hash globale, nel caso il metodo sia dichiarato come test, poi resettiamo la variabile a false.
La nostra “test suite” manca ancora di un meccanismo per eseguire i test:
def run_tests(klass) obj=klass.new for i in obj.methods.sort run_method obj, i end end def run_method(obj,name) if desc=UT[name] retval= obj.send(name) rescue false print desc,": ",retval, "\n" end endFinito! Visto quanto e’ stato semplice? E considerate che questo meccanismo e’ comunque molto potente, ci sono persone che hanno costruito interi framework su di esso :)