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, reflect
egy 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