Forståelse ‘selv’ i Ruby

i dag vil jeg gerne tale om self. Hvis du har programmeret Ruby i et stykke tid, har du sandsynligvis internaliseret ideen om self. Når du læser eller skriver et program, self er der i baghovedet.

men for mindre erfarne Rubyister kan self være forvirrende. Det ændrer sig altid, men det vises aldrig eksplicit i koden. Du forventes bare at vide det.

mange af de problemer, begyndere står overfor, skyldes ikke forståelse self. Hvis du nogensinde har “mistet” en instansvariabel eller forvirret over, hvilke data der er synlige for en blanding, så er det fordi du ikke forstod self i den sammenhæng.

i dette indlæg skal vi se på self i en række hverdagssituationer.

Hvad er selv?

du har måske hørt folk sige, at alt i Ruby er et objekt. Hvis det er sandt, betyder det, at hvert stykke kode, du skriver, “tilhører” et objekt.

self er en speciel variabel, der peger på det objekt, der “ejer” den aktuelt udførte kode. Ruby bruger self overalt:

  • for eksempel variabler: @myvar
  • til metode og konstant opslag
  • ved definition af metoder, klasser og moduler.

i teorien er self ret indlysende. Men i praksis er det let for vanskelige situationer at dukke op. Derfor skrev jeg dette indlæg.

eksempler på selv

vi vil gennemgå flere eksempler nu. Hvis de første virker for grundlæggende for dig, skal du bare fortsætte med at læse. De bliver mere avancerede.

inde i en instansmetode

i koden nedenfor er reflect en instansmetode. Det tilhører det objekt, vi oprettede via Ghost.new. Så self peger på dette objekt.

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

inde i en klassemetode

i dette eksempel er reflecten klassemetode på Ghost. Med klassemetoder “ejer” klassen selv metoden. self peger på klassen.

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

det fungerer det samme med” klasse ” metoder inde i moduler. For eksempel:

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

husk, klasser og moduler behandles som objekter i Ruby. Så denne adfærd er ikke så forskellig fra den forekomstmetode, vi så i det første eksempel.

inde i en klasse-eller moduldefinition

et træk ved Ruby, der gør det så godt egnet til rammer som Rails, er, at du kan udføre vilkårlig kode inde i klasse-og moduldefinitioner. Når du sætter kode inde i en klasse / modul definition, det kører ligesom enhver anden Ruby kode. Den eneste reelle forskel er værdien af self.

som du kan se nedenfor, self peger på den klasse eller det modul, der er ved at blive defineret.

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

indenfor blandingsmetoder

blandede metoder opfører sig ligesom “normale” instanseller klassemetoder, når det kommer til self. Det giver mening. Ellers ville blandingen ikke være i stand til at interagere med den klasse, du blandede den i.

Instansmetoder

selvom reflect – metoden blev defineret i modulet, er dens self forekomsten af den klasse, den blev blandet ind i.

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

klassemetoder

når vi extend en klasse, der skal blandes i klassemetoder, opfører self sig nøjagtigt som det gør i normale klassemetoder.

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

inde i metaklassen

chancerne er, at du har set denne populære genvej til at definere mange klassemetoder på en gang.

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

syntaksen class << foo er faktisk ret interessant. Det giver dig adgang til et objekts metaklasse-som også kaldes “singleton class” eller “eigenclass.”Jeg planlægger at dække metaclasses dybere i et fremtidigt indlæg. Men for nu skal du bare vide, at metaklassen er, hvor Ruby gemmer metoder, der er unikke for et bestemt objekt.

hvis du åbner self inde fra class << foo – blokken, får du metaklassen.

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

uden for enhver klasse

hvis du kører kode uden for en klasse, giver Ruby stadig self. Det peger på “main”, som er en forekomst af Object:

puts self.inspect # => main