Welchen Umfang hat ein „at“ sigil (@) geben im Ruby-Funktionen?
Frage
Es ist schon eine Weile her, seit ich das letzte Mal Ruby-Programmierung haben - Blick auf jemand anderem Code, sehe ich die @
Sigill in einer Funktion ( nicht ein Verfahren - extern zu jeder Klassendefinition), die ich verstand Instanz Mitglieder scoped werden.
Das Modul ist der implizite self
in Funktionen?
Lösung
In einer Top-Level-Funktion (noch ein Verfahren wirklich), du bist in einem etwas seltsamen Ort: eine globale „main“ Raum (die Eingabeaufforderung angezeigt, wenn Sie irb
ausführen oder versuchen, bei self
innerhalb einer solchen Funktion suchen) aber auch diese Funktionen als private Methoden in der Object
Klasse definiert ist.
$ cat foo
def foo
p self
p self.class
puts 'foo'
end
foo
Object.foo
$ ruby foo
main
Object
foo
foo:8: private method `foo' called for Object:Class (NoMethodError)
$
Sie können rund um diese schleichen durch explizit diese Methoden public
erklären, aber ich bin nicht sicher, ob ich das gefällt! Seltsamerweise, wenn Sie ein Top-Level-Methode innerhalb irb
definieren, dann können Sie es über die Klassenmethode Object#foo
aufrufen, ohne es öffentlich zu erklären.
Das ist also eine Art „impliziten Hauptnamensraum auf Object
gehackt (aber pssst jemand nicht sagen)“. @foo
innerhalb einer Funktion der obersten Ebene definiert ist, im Inneren Objekt, als einfaches altes Attribut zur Verfügung. Art. Wenn Ihr Top-Level-Methode @foo
gesetzt und Sie es nennen, ohne Scoping dann ist es in der Eigen wie main
Namespace deklariert, aber wenn Sie die Klassenmethode über Object
rufen dann erscheint @foo
innerhalb von Object
.
Ein weiteres Beispiel:
public
def set_foo
@foo = 'foo'
end
def get_foo
@foo
end
def Object.get_foo_again
@foo
end
set_foo
p get_foo
p Object.get_foo_again
Object.set_foo
p Object.get_foo_again
gibt
"foo" # @foo set in main
nil # @foo nil in Object
"foo" # @foo in Object
Die Umkehrung gilt auch.
Andere Tipps
Die Annahme, dass dies „eine Funktion, kein Verfahren“ ist falsch. All Ruby-Code erfolgt im Rahmen eines Objekts. Der „globale“ Kontext ist ein Objekt namens main
(versuchen ruby -e "puts self"
, wenn Sie es nicht glauben). Methods in dem oberen Bereich definiert werden Instanzmethoden Object. Dies bedeutet, dass das Verfahren zur Verfügung stehen wird überall , mit self
(und damit dem Zusammenhang, dass Instanzvariablen gehört), je nachdem, wo die Methode aufgerufen wird,
Ich denke, es Tive es zu einem Modul.
@ macht eine Variable eine Instanzvariable. Es klingt wie es ist kein Teil einer explizit deklarierten Klasse ist, so ist es in der Hauptsache zur Verfügung gehen, wie Chuck hingewiesen. Es ist einfacher, mit gutem Beispiel dargestellt:
$ irb
irb(main):001:0> @var = 1
=> 1
irb(main):002:0> class New
irb(main):003:1> def test
irb(main):004:2> puts @var
irb(main):005:2> end
irb(main):006:1> end
=> nil
irb(main):007:0> test = New.new
=> #<New:0xb7ccbc14>
irb(main):008:0> test.test
nil
=> nil
irb(main):009:0> def test2
irb(main):010:1> puts @var
irb(main):011:1> end
=> nil
irb(main):012:0> test2
1
=> nil