Î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, reflecteste 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