Înțelegerea sinelui în Ruby
astăzi aș vrea să vorbesc despre self
. Dacă programați Ruby de ceva vreme, probabil că ați interiorizat ideea self
. Ori de câte ori citiți sau scrieți un program, self
este acolo în spatele minții voastre.
dar pentru Rubyiștii mai puțin experimentați, self
poate fi derutant. Se schimbă mereu, dar nu este niciodată afișat în mod explicit în cod. Trebuie doar să știi.
multe dintre problemele cu care se confruntă începătorii sunt cauzate de neînțelegerea self
. Dacă ați „pierdut” vreodată o variabilă de instanță sau ați nedumerit ce date sunt vizibile pentru un mixin, atunci este pentru că nu ați înțeles self
în acest context.
în acest post, ne vom uita la self
într-o varietate de situații de zi cu zi.
ce este sinele?
este posibil să fi auzit oameni spunând că totul în Ruby este un obiect. Dacă este adevărat, înseamnă că fiecare bucată de cod pe care o scrieți „aparține” unui obiect.
self
este o variabilă specială care indică obiectul care „deține” codul care execută în prezent. Ruby foloseste self
everwhere:
- de exemplu variabile:
@myvar
- pentru Metodă și căutare constantă
- la definirea metodelor, claselor și modulelor.
teoretic, self
este destul de evident. Dar, în practică, este ușor să apară situații dificile. De aceea am scris acest post.
Exemple de sine
vom trece prin câteva exemple acum. Dacă primele par prea elementare pentru dvs., continuați să citiți. Ei devin mai avansați.
în interiorul unei metode de instanță
în codul de mai jos, reflect
este o metodă de instanță. Aparține obiectului pe care l-am creat prin Ghost.new
. Deci self
indică acel obiect.
class Ghost def reflect self endendg = Ghost.newg.reflect == g # => true
în interiorul unei metode de clasă
pentru acest exemplu, reflect
este o metodă de clasă de Ghost
. Cu metode de clasă, clasa însăși „deține” metoda. self
indică clasa.
class Ghost def self.reflect self endendGhost.reflect == Ghost # => true
acesta funcționează la fel cu” clasa ” metode în interiorul modulelor. De exemplu:
module Ghost def self.reflect self endend Ghost.reflect == Ghost # => true
amintiți-vă, clasele și modulele sunt tratate ca obiecte în Ruby. Deci acest comportament nu este atât de diferit de comportamentul metodei de instanță pe care l-am văzut în primul exemplu.
în interiorul unei clase sau modul definiție
o caracteristică a Ruby care face o astfel de potrivire bună pentru cadre, cum ar fi șine este că puteți executa cod arbitrar în interiorul clasă și modul definiții. Când puneți codul în interiorul unei clase/definiție modul, ruleaza la fel ca orice alt cod Ruby. Singura diferență reală este valoarea self
.
după cum puteți vedea mai jos, self
indică clasa sau modulul care este în curs de definire.
class Ghost self == Ghost # => trueend module Mummy self == Mummy # => trueend
în interiorul metodelor mixin
metodele mixte se comportă la fel ca metodele „normale” de instanță sau de clasă atunci când vine vorba de self
. Acest lucru are sens. În caz contrar, mixin nu ar putea interacționa cu clasa în care ați amestecat-o.
metode de instanță
chiar dacă metoda reflect
a fost definită în modul, self
este instanța clasei în care a fost amestecată.
module Reflection def reflect self endend class Ghost include Reflectionendg = Ghost.newg.reflect == g # => true
metode de clasă
când extend
o clasă de amestecat în metode de clasă, self
se comportă exact ca în metodele normale de clasă.
module Reflection def reflect self endend class Ghost extend ReflectionendGhost.reflect == Ghost # => true
în interiorul metaclass
sunt șanse ați văzut această comandă rapidă populare pentru definirea o mulțime de metode de clasă la o dată.
class Ghost class << self def method1 end def method2 end endend
sintaxa class << foo
este de fapt destul de interesantă. Acesta vă permite să accesați metaclass unui obiect-care este, de asemenea, numit „clasa singleton” sau „eigenclass.”Am de gând să acopere metaclasses mai profund într-un post viitor. Dar, deocamdată, trebuie doar să știți că metaclasa este locul în care Ruby stochează metode unice pentru un anumit obiect.
dacă accesați self
din interiorul blocului class << foo
, obțineți metaclasa.
class << "test" puts self.inspectend# => #<Class:#<String:0x007f8de283bd88>
în afara oricărei clase
dacă executați cod în afara oricărei clase, Ruby oferă încă self
. Acesta indică „main”, care este un exemplu de Object
:
puts self.inspect # => main