new - ruby initialize



Verwenden von Instanzvariablen in Klassenmethoden-Ruby (2)

Der Grund, warum Instanzvariablen für Klassen in Ruby funktionieren, ist, dass Ruby-Klassen selbst Instanzen sind (Instanzen der Klasse Class ). Probieren Sie es selbst aus, indem Sie DummyClass.class . Es gibt keine "statischen Methoden" im Sinne von C # in Ruby, da jede Methode für eine Instanz definiert (oder in diese vererbt) und für eine Instanz aufgerufen wird. Dementsprechend können sie auf alle Instanzvariablen zugreifen, die gerade auf der Liste verfügbar sind.

Da DummyClass eine Instanz ist, kann es durchaus eigene Instanzvariablen geben. Sie können sogar auf diese Instanzvariablen zugreifen, solange Sie einen Verweis auf die Klasse haben (was immer der Fall sein sollte, da Klassennamen Konstanten sind). Zu jedem Zeitpunkt können Sie ::DummyClass.instance_variable_get(:@arr) aufrufen und den aktuellen Wert dieser Instanzvariablen ::DummyClass.instance_variable_get(:@arr) .

Ob dies eine gute Sache ist, hängt von den Methoden ab .

Wenn @arr logisch der "Status" der Instanz / Klasse DummyClass , speichern Sie ihn in der Instanzvariablen. Wenn @arr nur in dummy_method2 als betriebliche Verknüpfung verwendet wird, übergeben Sie es als Argument. Um ein Beispiel zu geben, bei dem der Ansatz der Instanzvariablen verwendet wird, betrachten Sie ActiveRecord in Rails. Sie können dies tun:

u = User.new
u.name = "foobar"
u.save

Der Name, der dem Benutzer zugewiesen wurde, sind Daten, die dem Benutzer legitim sind. Wenn vor dem #save Aufruf gefragt wurde "Wie lautet der Name des Benutzers an dieser Stelle", würden Sie "foobar" beantworten. Wenn Sie weit genug in die Interna graben (Sie werden sehr weit und in viel Metaprogrammierung eintauchen, werden Sie feststellen, dass sie Instanzvariablen für genau dies verwenden).

Das von mir verwendete Beispiel enthält zwei getrennte öffentliche Aufrufe. Sehen Sie sich die #update_attributes Implementierung von #update_attributes , um einen Fall zu sehen, in dem Instanzvariablen trotz des Aufrufs nur eines Aufrufs verwendet werden. Der Methodenkörper wird einfach load(attributes, false) && save . Warum bekommt #save keine Argumente (wie den neuen name ) übergeben, obwohl es sich in dem Speicher von save befinden wird, in dem UPDATE users SET name='foobar' WHERE id=1; wie UPDATE users SET name='foobar' WHERE id=1; ? Dies liegt daran, dass der Name zum Beispiel Informationen sind, die zur Instanz gehören.

Umgekehrt können wir einen Fall betrachten, in dem Instanzvariablen keinen Sinn machen würden. Sehen Sie sich die Implementierung von #link_to_if , einer Methode, die ein boolean-ish-Argument (normalerweise ein Ausdruck im Quellcode) neben Argumenten akzeptiert, die normalerweise von #link_to akzeptiert werden, #link_to z. B. die URL, zu der ein Link erstellt werden soll. Wenn der boolesche Zustand wahr ist, muss der Rest der Argumente an #link_to und #link_to . Es wäre nicht sinnvoll, Instanzvariablen hier zuzuweisen, da Sie nicht sagen würden, dass der aufrufende Kontext (der Renderer) diese Informationen in der Instanz enthält. Der Renderer selbst verfügt nicht über eine "URL, auf die verlinkt werden soll", und sollte daher nicht in einer Instanzvariablen eingebettet sein.

https://src-bin.com

Ich bin ein Neuling in Rubin (ich bin eigentlich c # dev.), Also könnte diese Frage ein Noob sein. Ich habe eine Klasse wie unten und habe Instanzvariablen (Array) verwendet, um zu vermeiden, dass viele Methodenparameter verwendet werden.

Es funktioniert wie erwartet, aber ist dies eine gute Praxis? Eigentlich hätte ich nicht erwartet, dass das funktioniert hat, aber ich denke, Klassenmethoden funktionieren in anderen Sprachen nicht als statische Methoden. Daher frage ich mich, ob dies eine gute Praxis ist oder ob ich Probleme haben könnte, wenn ich diese Variablen als Klassenvariablen benutze alles auf.

class DummyClass
  def self.dummy_method1
    @arr = []
    # Play with that array
  end

  def self.dummy_method2
    # use @arr for something else
  end
end

Answer #1

Dies sind Klasseninstanzvariablen, die in Ruby durchaus legitim sind: Klassen sind auch Objekte (Instanzen von Class) und verfügen auch über Instanzvariablen.

Eine Sache, auf die Sie achten sollten, ist, dass jede Unterklasse ihren eigenen Satz von Klasseninstanzvariablen hat (schließlich handelt es sich dabei um verschiedene Objekte): Wenn Sie DummyClass Unterklassen DummyClass , können Klassenmethoden für die Unterklasse @arr nicht sehen.

Klassenvariablen ( @@foo ) sind natürlich umgekehrt: Die gesamte Klassenhierarchie hat die gleichen Klassenvariablen.





instance-variables