1.4.1.11. fejezet, Szimbólumok
A szimbólumok :valami formában definiálhatók. Szöveg jellege ellenére inkább hasonlít a Fixnum tipushoz, mert egyedi azonosítóval rendelkezik, az object_id-n keresztül.
puts( :helloworld.equal?( :helloworld ) ) #=> true puts( "helloworld".equal?( "helloworld" ) ) #=> false puts( 1.equal?( 1 ) ) #=> true
Az objektum tulajdonság elérhetőségét szabályzó kifejezésekben láttunk először szimbólumot:
attr_reader( :description ) attr_writer( :description ) attr_accessor( :name )
Case elágazásokban is használható:
case doThis when :deletefiles : puts( 'Now deleting files...') when :formatdisk : puts( 'Now formatting disk...') else puts( "Sorry, command not understood." ) end
Nézzük meg, mire is használható egy szimbólum.
module One class Fred end $f1 = :Fred def self.evalFred( aSymbol ) puts( eval( aSymbol.id2name ) ) end end module Two Fred = 1 $f2 = :Fred def self.evalFred( aSymbol ) puts( eval( aSymbol.id2name ) ) end end def Fred() puts( "hello from the Fred method" ) end $f3 = :Fred One::evalFred( $f1 ) Two::evalFred( $f2 ) method($f3).call puts One::evalFred( $f3 ) Two::evalFred( $f1 ) method($f2).call
Eredmények:
One::Fred 1 hello from the Fred method One::Fred 1 hello from the Fred method
Itt látható, hogy a szimbólum hatásköre hogyan változik, melyik modulra, metódusra, változóra hivatkozhatunk a szimbólumokkal az eval metódus felhasználásával. Modulokról a 12. fejezetben lesz még szó, és a dinamikus programozásnál bővebben megvizsgáljuk majd az eval-t. Most elégedjünk meg azzal, hogy string objektumokat értékel ki, a program futása közben összeállított utasításokat hajtathatunk vele végre. És most lepődhetünk meg igazán:
puts( $f1.object_id ) puts( $f2.object_id ) puts( $f3.object_id )
ugyanis mind a három globális változó object_id-ja egyező. Más szóval a module One-ban a :Fred szimbólum a Fred osztályra hivatkozik, a module Two-ban a Fred=1 konstansra, és végül a main hatókörében (szkópban) a Fred metódusra, viszont mindegyik metódushívás ugyan azt a szimbólumot használta.
Szimbólumok és változók
Definiáljunk két változót:
x = 1 xsymbol = :x
És végezzük el ismét az eval kiértékelést:
amethod( eval(:x.id2name))
Az id2name a Symbol osztály metódusa. A to_s metódusa ennek az osztálynak ugyanazt teszi, mint az id2name: szöveg alakítja a szimbólum nevét. Az x szimbólumból szöveggé alakított string-et az eval kiértékeli, és úgy látja, hogy egy x változót kell végrehajtania. Vagyis az amethod egy 1-es értéket kap argumentumként.
Most nézzük meg változókkal.
def amethod( somearg ) p( somearg ) # puts( "[class=#{somearg.class}]\n" ) #<= uncomment to verify classes end x = 1 # try changing this value to 100 or "hello world" xsymbol = :x puts( '- Test #1 ------------' ) puts('amethod( x )') amethod( x ) puts('amethod( :x )') amethod( :x ) puts( '- Test #2 ------------' ) puts('amethod( eval(:x.id2name))') amethod( eval(:x.id2name) ) puts( '- Test #3 ------------' ) amethod( xsymbol ) amethod( :xsymbol ) amethod( eval(:xsymbol.id2name)) amethod( eval( ( eval(:xsymbol.id2name)).id2name ) ) puts( '- Test #4 ------------' ) method(:amethod).call("") method(:amethod).call(eval(:x.id2name))
Az eredmények pedig:
- Test #1 ------------ amethod( x ) 1 amethod( :x ) :x - Test #2 ------------ amethod( eval(:x.id2name)) 1 - Test #3 ------------ :x :xsymbol :x 1 - Test #4 ------------ "" 1
Ha ez kicsit bonyolult, nézzük meg az alábbiakat:
def mymethod( somearg ) print( "I say: " << somearg ) end this_is_a_method_name = method(:mymethod)
Itt a method(:mymethod) a :mymethod szimbólum alapján keres egy metódust. Ha talál ilyet, visszatér a megfelelő nevű Method objektummal. És ha ez tényleg egy metódus, miért ne hívhatnánk meg?
this_is_a_method_name.call( "hello world" ) #=> Ezt írja ki: I say: hello world
Miért használjunk szimbólumokat?
A szimbólumoknak speciális helye van a dinamikus programozásban. Például új metódus készíthető vele:
class Array define_method( :aNewMethod, lambda{ |*args| puts( args.inspect) } ) end
Aztán le is ellenőrizhető, hogy létrejött:
Array.method_defined?( :aNewMethod ) #=> returns: true
amit aztán meg is hívhatunk:
[].aNewMethod( 1,2,3 ) #=> returns: [1,2,3]
El is távolíthatjuk a metódust, ha nincs rá szükségünk
class Array remove_method( :aNewMethod ) end
A dinamikus programozásra nagymértékben támaszkodik a Rails.
Közelebbről megvizsgálva
Egy szimbólum, lényegében egy mutató a szimbólum táblázatra. A szimbólum tábla egy belső lista a Ruby-ban definiált azonosítókról, mint a változó vagy metódus név. Ha közelebbről megnézzük a Ruby-ban definiált szimbólumokat, használjuk az alábbi utasítást:
p( Symbol.all_symbols )
Egy csomó szimbólumot kapunk, amit részleteiben is megnézhetünk, hiszen egy tömbről van szó, habár sorba nem rendezhető, mert ezt a metódust nem örökölte. Azért megoldható ez is, ha string-é alakítjuk mindet, és egy tömbbe tároljuk a string-eket, ami máris sorba rendezhető. Az alábbiakban pont ezt csináljuk.
str_arr = Symbol.all_symbols.collect{ |s| s.to_s } puts( str_arr.sort )
- A hozzászóláshoz be kell jelentkezni