Zrozumienie ’ ja ’ w Ruby
dzisiaj chciałbym porozmawiać o self
. Jeśli programujesz Ruby od jakiegoś czasu, prawdopodobnie zinternalizowałeś ideę self
. Ilekroć czytasz lub piszesz program, self
jest z tyłu twojego umysłu.
ale dla mniej doświadczonych Rubyistów self
może być zaskakujące. To się zawsze zmienia, ale nigdy nie jest wyraźnie pokazane w kodzie. Po prostu musisz wiedzieć.
wiele problemów, z którymi borykają się początkujący, jest spowodowanych niezrozumieniem self
. Jeśli kiedykolwiek „zgubiłeś” zmienną instancji lub zastanawiałeś się, jakie dane są widoczne dla mixina, to dlatego, że nie zrozumiałeś self
w tym kontekście.
w tym poście przyjrzymy się self
w różnych codziennych sytuacjach.
czym jest ja?
być może słyszałeś, że ludzie mówią, że wszystko w Ruby jest obiektem. Jeśli to prawda, oznacza to, że każdy zapisany fragment kodu „należy” do jakiegoś obiektu.
self
jest zmienną specjalną, która wskazuje na obiekt, który „jest właścicielem” aktualnie wykonywanego kodu. Ruby używa self
everwhere:
- na przykład zmienne:
@myvar
- dla metody i stałego wyszukiwania
- przy definiowaniu metod, klas i modułów.
w teorii self
jest dość oczywiste. Ale w praktyce łatwo jest wyskoczyć w trudnych sytuacjach. Dlatego napisałem ten post.
przykłady jaźni
przejdziemy teraz przez kilka przykładów. Jeśli pierwsze wydają ci się zbyt proste, po prostu czytaj dalej. Stają się bardziej zaawansowane.
wewnątrz metody instancji
w poniższym kodzie reflect
jest metodą instancji. Należy do obiektu, który stworzyliśmy za pomocą Ghost.new
. Więc self
wskazuje na ten obiekt.
class Ghost def reflect self endendg = Ghost.newg.reflect == g # => true
wewnątrz metody klasy
w tym przykładzie reflect
jest metodą klasy Ghost
. W przypadku metod klasowych, sama klasa „posiada” metodę. self
punkty do klasy.
class Ghost def self.reflect self endendGhost.reflect == Ghost # => true
działa to tak samo z metodami „class” wewnątrz modułów. Na przykład:
module Ghost def self.reflect self endend Ghost.reflect == Ghost # => true
pamiętaj, że klasy i moduły są traktowane jako obiekty w Ruby. Więc to zachowanie nie różni się zbytnio od zachowania metody instancji, które widzieliśmy w pierwszym przykładzie.
wewnątrz definicji klasy lub modułu
jedną z cech Rubiego, która sprawia, że jest tak dobrze dopasowany do frameworków takich jak Rails, jest to, że możesz wykonać dowolny kod wewnątrz definicji klas i modułów. Kiedy umieszczasz kod wewnątrz definicji klasy/modułu, działa on tak jak każdy inny kod Ruby. Jedyną rzeczywistą różnicą jest wartość self
.
jak widać poniżej, self
wskazuje na klasę lub moduł, który jest w trakcie definiowania.
class Ghost self == Ghost # => trueend module Mummy self == Mummy # => trueend
wewnątrz metod mixin
metody Mixed-in zachowują się jak „normalne” metody instancji lub klasy, jeśli chodzi o self
. To ma sens. W przeciwnym razie mixin nie byłby w stanie współdziałać z klasą, do której go dodałeś.
metody instancji
mimo że metoda reflect
została zdefiniowana w module, jej self
jest instancją klasy, do której została zmieszana.
module Reflection def reflect self endend class Ghost include Reflectionendg = Ghost.newg.reflect == g # => true
metody klasy
kiedy my extend
Klasa do mieszania w metodach klasy, self
zachowuje się dokładnie tak samo jak w normalnych metodach klasy.
module Reflection def reflect self endend class Ghost extend ReflectionendGhost.reflect == Ghost # => true
wewnątrz metaclass
Prawdopodobnie widziałeś ten popularny skrót do definiowania wielu metod klas naraz.
class Ghost class << self def method1 end def method2 end endend
składnia class << foo
jest całkiem ciekawa. Umożliwia dostęp do metaklasu obiektu-który jest również nazywany „klasą Singletona” lub ” eigenclass.”Planuję głębiej opisać metaklasy w przyszłym poście. Ale na razie musisz tylko wiedzieć, że metaclass jest miejscem, w którym Ruby przechowuje metody, które są unikalne dla określonego obiektu.
jeśli uzyskasz dostęp do self
z wnętrza bloku class << foo
, otrzymasz metaclass.
class << "test" puts self.inspectend# => #<Class:#<String:0x007f8de283bd88>
poza klasą
jeśli używasz kodu poza klasą, Ruby nadal dostarcza self
. Wskazuje na „główny”, który jest przykładem Object
:
puts self.inspect # => main