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