`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