Forstå ‘ selv` I Ruby

I Dag vil jeg snakke om self. Hvis Du har programmert Ruby en stund, har du sannsynligvis internalisert ideen om self. Når du leser eller skriver et program, self er det i bakhodet ditt.

men for mindre erfarne Rubyister kan self være forvirrende. Det er alltid i endring, men det er aldri eksplisitt vist i koden. Du er bare forventet å vite.

mange av problemene nybegynnere står overfor er forårsaket av ikke å forstå self. Hvis du noen gang har «mistet» en forekomstvariabel eller forvirret over hvilke data som er synlige for en mixin, så er det fordi du ikke forstod self i den konteksten.

I dette innlegget skal vi se på self i en rekke hverdagssituasjoner.

Hva er selv?

du har kanskje hørt folk si at Alt I Ruby er et objekt. Hvis det er sant, betyr det at hvert stykke kode du skriver «tilhører» et objekt.

self er en spesiell variabel som peker på objektet som «eier» den nåværende koden. Ruby bruker self everwhere:

  • for eksempel variabler: @myvar
  • for metode og konstant oppslag
  • når du definerer metoder, klasser og moduler.

i teorien er self ganske åpenbart. Men i praksis er det lett for vanskelige situasjoner å dukke opp. Det er derfor jeg skrev dette innlegget.

eksempler på selv

Vi skal gå gjennom flere eksempler nå. Hvis de første virker for grunnleggende for deg, bare fortsett å lese. De blir mer avanserte.

Inne i en instansmetode

i koden nedenfor er reflect en instansmetode. Den tilhører objektet vi opprettet via Ghost.new. Så self peker på det objektet.

class Ghost def reflect self endendg = Ghost.newg.reflect == g # => true

Inne i en klassemetode

for dette eksemplet er reflect en klassemetode på Ghost. Med klassemetoder «eier klassen selv» metoden. self peker på klassen.

class Ghost def self.reflect self endendGhost.reflect == Ghost # => true

det fungerer det samme med» klasse » metoder inne i moduler. For eksempel:

module Ghost def self.reflect self endend Ghost.reflect == Ghost # => true

husk at klasser og moduler behandles som objekter i Ruby. Så denne oppførselen er ikke så forskjellig fra forekomstmetoden vi så i det første eksemplet.

Inne i en klasse-eller moduldefinisjon

En funksjon Av Ruby som gjør Det så bra for rammer som Rails, er at du kan utføre vilkårlig kode i klasse – og moduldefinisjoner. Når du setter koden inne i en klasse / modul definisjon, går det akkurat som alle Andre Ruby kode. Den eneste virkelige forskjellen er verdien av self.

som du kan se nedenfor, peker self på klassen eller modulen som er i ferd med å bli definert.

class Ghost self == Ghost # => trueend module Mummy self == Mummy # => trueend 

Inside mixin metoder

Mixed-in metoder oppfører seg akkurat som «normal» forekomst eller klasse metoder når det gjelder self. Dette gir mening. Ellers ville mixin ikke kunne samhandle med klassen du blandet den inn i.

Instansmetoder

selv om metoden reflect ble definert i modulen, er dens self forekomsten av klassen den ble blandet inn i.

module Reflection def reflect self endend class Ghost include Reflectionendg = Ghost.newg.reflect == g # => true

Klassemetoder

når vi extend en klasse å blande i klassemetoder, self oppfører seg akkurat som det gjør i normale klassemetoder.

module Reflection def reflect self endend class Ghost extend ReflectionendGhost.reflect == Ghost # => true

Inne i metaclass

Sjansene er At du har sett denne populære snarveien for å definere mange klassemetoder samtidig.

class Ghost class << self def method1 end def method2 end endend

syntaksen class << foo er faktisk ganske interessant. Den lar deg få tilgang til et objekt metaclass – som også kalles «singleton class» eller » eigenclass.»Jeg planlegger å dekke metaklasser dypere i et fremtidig innlegg. Men for nå trenger du bare å vite at metaclass er der Ruby lagrer metoder som er unike for et bestemt objekt.

hvis du får tilgang til self fra innsiden av class << foo – blokken, får du metaclassen.

class << "test" puts self.inspectend# => #<Class:#<String:0x007f8de283bd88>

Utenfor en klasse

Hvis Du kjører kode utenfor en klasse, Gir Ruby fortsatt self. Det peker på «main», som er en forekomst av Object:

puts self.inspect # => main