`Selbst` in Ruby verstehen
Heute möchte ich über self
sprechen. Wenn Sie Ruby schon eine Weile programmieren, haben Sie wahrscheinlich die Idee von self
verinnerlicht. Wann immer Sie ein Programm lesen oder schreiben, ist self
im Hinterkopf.
Aber für weniger erfahrene Rubyisten kann self
verwirrend sein. Es ändert sich immer, aber es wird nie explizit im Code angezeigt. Von dir wird nur erwartet, dass du es weißt.
Viele der Probleme, mit denen Anfänger konfrontiert sind, werden dadurch verursacht, dass sie self
nicht verstehen. Wenn Sie jemals eine Instanzvariable „verloren“ haben oder verwirrt darüber sind, welche Daten für ein Mixin sichtbar sind, dann liegt das daran, dass Sie self
in diesem Kontext nicht verstanden haben.
In diesem Beitrag werden wir self
in einer Vielzahl von Alltagssituationen betrachten.
Was ist Selbst?
Sie haben vielleicht Leute sagen hören, dass alles in Ruby ein Objekt ist. Wenn das stimmt, bedeutet das, dass jeder Code, den Sie schreiben, zu einem Objekt „gehört“.
self
ist eine spezielle Variable, die auf das Objekt zeigt, das den aktuell ausgeführten Code „besitzt“. Ruby verwendet self
überall:
- Für Instanzvariablen:
@myvar
- Für Methoden- und konstante Suche
- Beim Definieren von Methoden, Klassen und Modulen.
Theoretisch ist self
ziemlich offensichtlich. In der Praxis können jedoch leicht knifflige Situationen auftreten. Deshalb habe ich diesen Beitrag geschrieben.
Beispiele für self
Wir werden jetzt einige Beispiele durchgehen. Wenn Ihnen die ersten zu einfach erscheinen, lesen Sie einfach weiter. Sie werden fortgeschrittener.
Innerhalb einer Instanzmethode
Im folgenden Code ist reflect
eine Instanzmethode. Es gehört zu dem Objekt, das wir über Ghost.new
erstellt haben. Also self
zeigt auf dieses Objekt.
class Ghost def reflect self endendg = Ghost.newg.reflect == g # => true
Innerhalb einer Klassenmethode
In diesem Beispiel ist reflect
eine Klassenmethode von Ghost
. Bei Klassenmethoden „besitzt“ die Klasse selbst die Methode. self
zeigt auf die Klasse.
class Ghost def self.reflect self endendGhost.reflect == Ghost # => true
Es funktioniert genauso mit „Klassen“ -Methoden innerhalb von Modulen. Zum Beispiel:
module Ghost def self.reflect self endend Ghost.reflect == Ghost # => true
Denken Sie daran, dass Klassen und Module in Ruby als Objekte behandelt werden. Dieses Verhalten unterscheidet sich also nicht wesentlich von dem Verhalten der Instanzmethode, das wir im ersten Beispiel gesehen haben.
Innerhalb einer Klassen- oder Moduldefinition
Eine Funktion von Ruby, die es so gut für Frameworks wie Rails macht, ist, dass Sie beliebigen Code innerhalb von Klassen- und Moduldefinitionen ausführen können. Wenn Sie Code in eine Klassen- / Moduldefinition einfügen, wird er wie jeder andere Ruby-Code ausgeführt. Der einzige wirkliche Unterschied ist der Wert von self
.
Wie Sie unten sehen können, zeigt self
auf die Klasse oder das Modul, das gerade definiert wird.
class Ghost self == Ghost # => trueend module Mummy self == Mummy # => trueend
Innerhalb von Mixin-Methoden
Mixed-in-Methoden verhalten sich wie „normale“ Instanz- oder Klassenmethoden, wenn es um self
geht. Das macht Sinn. Andernfalls könnte das Mixin nicht mit der Klasse interagieren, in die Sie es gemischt haben.
Instanzmethoden
Obwohl die reflect
Methode im Modul definiert wurde, ist ihre self
die Instanz der Klasse, in die sie gemischt wurde.
module Reflection def reflect self endend class Ghost include Reflectionendg = Ghost.newg.reflect == g # => true
Klassenmethoden
Wenn wir extend
eine Klasse in Klassenmethoden mischen, self
verhält sich genau wie in normalen Klassenmethoden.
module Reflection def reflect self endend class Ghost extend ReflectionendGhost.reflect == Ghost # => true
In der Metaklasse
haben Sie wahrscheinlich diese beliebte Verknüpfung zum gleichzeitigen Definieren vieler Klassenmethoden gesehen.
class Ghost class << self def method1 end def method2 end endend
Die class << foo
Syntax ist eigentlich ziemlich interessant. Damit können Sie auf die Metaklasse eines Objekts zugreifen, die auch als „Singleton-Klasse“ oder „Eigenklasse“ bezeichnet wird.“ Ich habe vor, Metaklassen in einem zukünftigen Beitrag genauer zu behandeln. Im Moment müssen Sie jedoch nur wissen, dass Ruby in der Metaklasse Methoden speichert, die für ein bestimmtes Objekt eindeutig sind.
Wenn Sie innerhalb des class << foo
-Blocks auf self
zugreifen, erhalten Sie die Metaklasse.
class << "test" puts self.inspectend# => #<Class:#<String:0x007f8de283bd88>
Außerhalb einer Klasse
Wenn Sie Code außerhalb einer Klasse ausführen, bietet Ruby weiterhin self
. Es zeigt auf „main“, was eine Instanz von Object
:
puts self.inspect # => main