Megértése ‘self’ Ruby

ma szeretnék beszélni self. Ha egy ideje programozza a Ruby-t, akkor valószínűleg internalizálta a selfötletét. Amikor egy programot olvasol vagy írsz, a self ott van a fejedben.

de a kevésbé tapasztalt Rubyisták számára az self zavaró lehet. Mindig változik, de soha nem jelenik meg kifejezetten a kódban. Csak azt várják Tőled, hogy tudd.

a kezdők sok problémáját az okozza, hogy nem értik self. Ha valaha is “elveszett” egy példányváltozót, vagy zavarba jött, hogy milyen adatok láthatók a mixin számára, akkor az azért van, mert nem értette a self – et ebben az összefüggésben.

ebben a bejegyzésben fogjuk nézni self a különböző mindennapi helyzetekben.

mi az én?

lehet, hogy hallotta, hogy az emberek azt mondják, hogy a Ruby-ban minden tárgy. Ha ez igaz, ez azt jelenti, hogy minden kóddarab, amelyet írsz,” tartozik ” valamilyen objektumhoz.

self egy speciális változó, amely arra az objektumra mutat, amely “birtokolja” a jelenleg végrehajtó kódot. Ruby használ self everwhere:

  • például változók: @myvar
  • metódus és állandó keresés esetén
  • metódusok, osztályok és modulok meghatározásakor.

elméletileg a self elég nyilvánvaló. De a gyakorlatban a trükkös helyzetek könnyen felbukkanhatnak. Ezért írtam ezt a bejegyzést.

példák önmagára

most több példát fogunk áttekinteni. Ha az elsők túl alapvetőnek tűnnek számodra, csak olvass tovább. Egyre fejlettebbek.

egy példány metódus belsejében

az alábbi kódban a reflect egy példány metódus. Az objektumhoz tartozik, amelyet a Ghost.new segítségével hoztunk létre. Tehát self erre az objektumra mutat.

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

belül egy osztály módszer

ebben a példában, reflectegy osztály módszer Ghost. Osztálymódszerekkel maga az osztály “birtokolja” a módszert. self az osztályra mutat.

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

ugyanúgy működik a modulokon belüli” osztály ” módszerekkel. Például:

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

ne feledje, hogy az osztályokat és modulokat objektumként kezelik a Ruby-ban. Tehát ez a viselkedés nem különbözik annyira a példány metódus viselkedésétől, amelyet az első példában láttunk.

Inside of a class or module definition

a Ruby egyik jellemzője, hogy olyan jól illeszkedik a keretrendszerekhez, mint a Rails, hogy tetszőleges kódot futtathat az osztály-és moduldefiníciókon belül. Amikor a kódot egy osztály/modul definícióba helyezi, ugyanúgy fut, mint bármely más Ruby kód. Az egyetlen valódi különbség a self értéke.

amint az alább látható, a self a definiálás alatt álló osztályra vagy modulra mutat.

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

belső mixin módszerek

a kevert módszerek ugyanúgy viselkednek, mint a “normál” példány vagy osztály módszerek, amikor a self -ről van szó. Ennek van értelme. Ellenkező esetben a mixin nem lenne képes kölcsönhatásba lépni azzal az osztállyal, amelybe keverte.

példány metódusok

annak ellenére, hogy a reflect metódust definiálták a modulban, annak self annak az osztálynak a példánya, amelybe keverték.

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

osztály metódusok

amikor extend osztályt keverünk osztály metódusokban, self pontosan úgy viselkedik, mint a normál osztály metódusokban.

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

a metaclass belsejében

valószínű, hogy látta ezt a népszerű parancsikont, amely egyszerre sok osztálymódszert határoz meg.

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

a class << foo szintaxis valójában nagyon érdekes. Ez lehetővé teszi a hozzáférést egy objektum metaclass-amely más néven a “singleton class” vagy ” saját osztály.”Azt tervezem, hogy a metaclasses mélyebben foglalkozik egy jövőbeli bejegyzésben. De egyelőre csak tudnia kell, hogy a metaclass az, ahol a Ruby egy adott objektumra jellemző módszereket tárol.

ha a self – et a class << foo blokk belsejéből éri el, akkor megkapja a metaklasst.

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

bármely osztályon kívül

ha bármely osztályon kívül fut a kód, A Ruby továbbra is biztosítja a self értéket. A “fő” – re mutat, amely a Object:

puts self.inspect # => main