Capire ‘ sé ‘ in Ruby

Oggi mi piacerebbe parlare di self. Se hai programmato Ruby per un po’, probabilmente hai interiorizzato l’idea di self. Ogni volta che leggi o scrivi un programma, self è lì nella parte posteriore della tua mente.

Ma per i rubisti meno esperti, self può essere sconcertante. Cambia sempre, ma non viene mai mostrato esplicitamente nel codice. Ci si aspetta solo che tu lo sappia.

Molti dei problemi che i principianti affrontano sono causati dalla non comprensione self. Se hai mai “perso” una variabile di istanza o perplesso su quali dati sono visibili a un mixin, allora è perché non hai capito self in quel contesto.

In questo post, vedremo self in una varietà di situazioni quotidiane.

Che cosa è sé?

Potresti aver sentito dire che tutto in Ruby è un oggetto. Se questo è vero significa che ogni pezzo di codice che scrivi “appartiene” a qualche oggetto.

self è una variabile speciale che punta all’oggetto che “possiede” il codice attualmente in esecuzione. Ruby utilizza self everwhere:

  • Per esempio variabili: @myvar
  • Per il metodo e la ricerca costante
  • Quando si definiscono metodi, classi e moduli.

In teoria, self è abbastanza ovvio. Ma in pratica, è facile per le situazioni difficili a pop-up. Ecco perché ho scritto questo post.

Esempi di sé

Stiamo andando a passo attraverso diversi esempi ora. Se i primi sembrano troppo basilari per te, continua a leggere. Diventano più avanzati.

All’interno di un metodo di istanza

Nel codice seguente, reflect è un metodo di istanza. Appartiene all’oggetto che abbiamo creato tramite Ghost.new. Quindi self punta a quell’oggetto.

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

All’interno di un metodo di classe

Per questo esempio, reflect è un metodo di classe di Ghost. Con i metodi di classe, la classe stessa “possiede” il metodo. self indica la classe.

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

Funziona allo stesso modo con i metodi di” classe ” all’interno dei moduli. Ad esempio:

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

Ricorda, le classi e i moduli sono trattati come oggetti in Ruby. Quindi questo comportamento non è così diverso dal comportamento del metodo di istanza che abbiamo visto nel primo esempio.

All’interno di una definizione di classe o modulo

Una caratteristica di Ruby che lo rende così adatto a framework come Rails è che è possibile eseguire codice arbitrario all’interno delle definizioni di classe e modulo. Quando si inserisce il codice all’interno di una definizione di classe/modulo, viene eseguito come qualsiasi altro codice Ruby. L’unica vera differenza è il valore di self.

Come puoi vedere di seguito, self punta alla classe o al modulo che è in fase di definizione.

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

All’interno dei metodi mixin

I metodi misti si comportano proprio come i metodi di istanza o classe “normali” quando si tratta di self. Questo ha senso. Altrimenti il mixin non sarebbe in grado di interagire con la classe in cui lo hai mescolato.

Metodi di istanza

Anche se il metodo reflect è stato definito nel modulo, il suo self è l’istanza della classe in cui è stato mescolato.

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

Metodi di classe

Quando abbiamo extend una classe per mescolare in metodi di classe, self si comporta esattamente come nei metodi di classe normali.

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

All’interno di metaclass

È probabile che tu abbia visto questa scorciatoia popolare per definire un sacco di metodi di classe contemporaneamente.

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

La sintassi class << foo è in realtà piuttosto interessante. Consente di accedere alla metaclasse di un oggetto, che viene anche chiamata “classe singleton” o “eigenclass.”Ho intenzione di coprire metaclassi più profondamente in un post futuro. Ma per ora, devi solo sapere che la metaclasse è dove Ruby memorizza i metodi che sono unici per un oggetto specifico.

Se si accede a self dall’interno del blocco class << foo, si ottiene la metaclasse.

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

Al di fuori di qualsiasi classe

Se stai eseguendo codice al di fuori di qualsiasi classe, Ruby fornisce ancora self. Punta a “main”, che è un’istanza di Object:

puts self.inspect # => main