Der Grund dafür, dass ff
in der test
-Methodendefinition nicht verfügbar ist, besteht einfach darin, dass Methoden (die mit dem Schlüsselwort def
erstellt wurden) einen neuen Bereich erstellen. Gleiches gilt für das Definieren von Klassen und Modulen mit den Schlüsselwörtern class
bzw. module
.
Die Rolle von main
(das Objekt der obersten Ebene) ist in dieser Situation fast völlig irrelevant für die Frage des Geltungsbereichs.
Wenn Sie möchten, dass Ihre Methode test
Zugriff auf im Definitionskontext definierte Locals hat, verwenden Sie die Methode define_method
(oder in Ihrem Fall die Methode define_singleton_method
), siehe hier:
Im Gegensatz zum Schlüsselwort def
erstellt die Methodenfamilie define_method
keine neuen Bereiche, sondern schließt über den aktuellen Bereich und erfasst alle lokalen Variablen.
Der Grund dafür, dass @ff
im nächsten Beispiel von @soup verwendet wurde, ist nicht, dass main
irgendwie ein "Spezialfall" ist, sondern dass ein auf oberster Ebene definierter ivar ein ivar von main
und ist Dies ist für eine Methode zugänglich, die auf main
aufgerufen wird.
Was ist jedoch die Beziehung der Methode test
zu main
? Es ist keine Methode on nur main
selbst - es ist tatsächlich eine private Instanzmethode, die in der Klasse Object
definiert ist. Dies bedeutet, dass die Methode test
für fast jedes Objekt in Ihrem Ruby-Programm als private Methode verfügbar wäre. Alle auf der obersten Ebene definierten Methoden ( main
) sind tatsächlich als private Instanzmethoden in der Klasse Object
definiert.
Weitere Informationen zur obersten Ruby-Ebene finden Sie in diesem Artikel: Ссылка
Der Ruby-Bereich ist einfach und komplex.
Zuerst müssen Sie daran denken, dass alles ein Objekt ist und alles einen Bereich hat.
Um Ihre Frage direkt zu beantworten, ist main
ein Objekt und wenn Sie def x...
schreiben, definieren Sie eine Methode für das Objekt main
Beobachten Sie in pyr / irb:
%Vor%Also wenn du schreibst
%Vor%Was du wirklich tust, ist
%Vor% Was nicht funktioniert, weil ff
den Gültigkeitsbereich nicht überschreitet. Um dies zu beheben, musst du ff
in eine Instanzvariable umwandeln, also setze den Namen mit @
voran. Folgendes wird funktionieren:
Beachten Sie, dass dies ein Sonderfall für main
als reguläre Klassen zu sein scheint, siehe unten.
Wenn wir eine eigene Testklasse haben:
%Vor% Dies schlägt fehl, weil ff
nicht wie erwartet im richtigen Bereich definiert ist. Es wird stattdessen darauf beschränkt, wenn der Parser unsere Klassendeklaration ausführt.
Also versuchen wir es mit dem obigen Fix:
%Vor%Das ist seltsam.
Lässt diese Methode hinzufügen:
%Vor%Warum ist @ff nil?
Folgendes könnte dies verdeutlichen:
%Vor%Wenn wir das ausführen, erhalten wir folgende Ausgabe:
%Vor% Wie Sie sehen können, läuft der Interpreter genau wie anderswo über unsere Klassendeklaration in der Reihenfolge und gibt unsere puts
-Anweisungen aus. Das wird interessanter, wenn wir Methoden aufrufen. Das Schreiben von @instance = ...
ist das gleiche wie das Schreiben von self.instance = ...
, also können Sie raten, wo wir die Instanz definiert haben? Ja, auf dem Klassenobjekt Test2 (kein Test2-Objekt).
Das ist der Grund, warum wir bei Aufruf von test
nichts ausgeben, weil test
, self
sich auf das instanziierte Test2
-Objekt bezieht, nicht Test2 class object
(wo wir @instance setzen) etwas!). Aus diesem Grund richten Sie Ihre Instanzvariablen in initialize
ein, wobei self
auf das tatsächliche Objekt zeigt.
Sie können sehen, wenn wir eine Klassenmethode über self.class_test
definieren und dann diese Methode für das Klassenobjekt Test2 ( Test2.class_test
) aufrufen, erhalten wir die erwartete Ausgabe, weil in diesem Bereich @instance
definiert wurde.
Ich hoffe, das hat einen Sinn ergeben.
Der Bereich Ссылка kann helfen, etwas von diesem Wissen zu festigen.
In Ruby hat ein Name ohne Sigil immer "lokalen" Geltungsbereich. Ruby verwendet lexikalisches Scoping, also bezieht sich der Name innerhalb einer Methode immer nur auf diese Methode.
Die anderen Bereiche sind global, Instanz und Klasse. Hier ist ein gutes Dokument über sie: Ссылка
Es gibt einige Möglichkeiten, Ihr Problem zu lösen. Mein Favorit wäre, das als Argument gedruckte Ding weiterzugeben:
%Vor%Wahrscheinlicher ist es, dass Sie das kapseln, was Sie in einer Klasse tun und eine Instanzvariable verwenden.
Sie könnten auch einfach eine globale Variable ($ ff) verwenden, aber auf diese Weise liegt Wahnsinn.
Warum kann ich nicht auf eine lokale Variable innerhalb einer Methode in Ruby zugreifen?
Weil es eine lokale Variable ist. Lokale Variablen sind lokal für den Bereich, in dem sie definiert sind. Deshalb werden sie schließlich als "lokale Variablen" bezeichnet.
In diesem Fall haben Sie im Skriptbereich eine lokale Variable definiert, die im Skriptbereich und nirgendwo anders sichtbar ist.
Tags und Links ruby