Begrip van` zelf ‘ in Ruby

vandaag wil ik het hebben over self. Als je Ruby al een tijdje programmeert, heb je waarschijnlijk het idee van selfgeïnternaliseerd. Wanneer u een programma leest of schrijft, zit self in uw achterhoofd.

maar voor minder ervaren Rubyisten kan self verbijsterend zijn. Het verandert altijd, maar het wordt nooit expliciet weergegeven in de code. Je moet het gewoon weten.

veel van de problemen waarmee beginners worden geconfronteerd, worden veroorzaakt door het niet begrijpen van self. Als je ooit een instance variabele hebt” verloren ” of je hebt afgevraagd welke data zichtbaar is voor een mixin, dan is dat omdat je self in die context niet begreep.

in dit artikel gaan we naar self kijken in verschillende dagelijkse situaties.

Wat is self?

u hebt misschien mensen horen zeggen dat alles in Ruby een object is. Als dat waar is betekent dit dat elk stukje code dat je schrijft “behoort” tot een object.

self is een speciale variabele die verwijst naar het object dat de huidige uitvoerende code “bezit”. Ruby gebruikt self overal:

  • bijvoorbeeld variabelen: @myvar
  • voor methode en constante lookup
  • bij het definiëren van methoden, klassen en modules.

in theorie is self vrij duidelijk. Maar in de praktijk, het is gemakkelijk voor lastige situaties opduiken. Daarom schreef ik dit bericht.

voorbeelden van zelf

we gaan nu een aantal voorbeelden doornemen. Als de eerste lijken te basic voor u, gewoon blijven lezen. Ze worden geavanceerder.

binnen een instantiemethode

in de onderstaande code is reflect een instantiemethode. Het behoort tot het object dat we hebben gemaakt via Ghost.new. Dus self wijst naar dat object.

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

Inside of a class method

in dit voorbeeld is reflect een class method van Ghost. Met klassemethoden “bezit” de klasse zelf de methode. self wijst naar de klasse.

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

het werkt hetzelfde met “klasse” methoden in modules. Bijvoorbeeld::

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

onthoud, klassen en modules worden behandeld als objecten in Ruby. Dus dit gedrag is niet zo verschillend van het gedrag van de instantie methode die we zagen in het eerste voorbeeld.

binnen een klasse of module definitie

een eigenschap van Ruby die het zo goed geschikt maakt voor frameworks zoals Rails is dat je willekeurige code kunt uitvoeren binnen klasse en module definities. Wanneer je code in een klasse/module definitie plaatst, draait het net als elke andere Ruby code. Het enige echte verschil is de waarde van self.

zoals u hieronder kunt zien, wijst self naar de klasse of module die wordt gedefinieerd.

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

Inside mixin methods

Mixed-in methods gedragen zich net als “normale” instance of class methods als het gaat om self. Dit is logisch. Anders zou de mixin niet in staat zijn om te communiceren met de klasse waarin je het mixte.

Instance methods

hoewel de reflect methode is gedefinieerd in de module, is self het instance van de klasse waarin het is gemengd.

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

Klasse methoden

wanneer we extend een klasse om te mengen in klasse methoden, self gedraagt zich precies zoals het doet in normale klasse methoden.

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

in de metaclass

is de kans groot dat u deze populaire snelkoppeling hebt gezien voor het definiëren van veel klassemethoden tegelijk.

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

de class << foo syntaxis is eigenlijk best interessant. Het geeft je toegang tot de metaclass van een object – die ook wel de “singleton klasse” of “eigenklasse.”Ik ben van plan om metaclasses dieper te behandelen in een toekomstige functie. Maar voor nu, je hoeft alleen maar te weten dat de metaclass is waar Ruby slaat methoden die uniek zijn voor een specifiek object.

als u self vanuit het class << foo – blok opent, krijgt u de metaclass.

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

buiten elke klasse

als je code draait buiten elke klasse, biedt Ruby nog steeds self. Het wijst naar “main”, dat is een instantie van Object:

puts self.inspect # => main