Erstellen Sie Modulvariablen in Ruby

111

Gibt es eine Möglichkeit, eine Variable in einem Modul in Ruby zu erstellen, die sich ähnlich wie eine Klassenvariable verhält? Damit meine ich, dass auf es zugegriffen werden kann, ohne eine Instanz des Moduls zu initialisieren, aber es kann geändert werden (im Gegensatz zu Konstanten in Modulen).

Mark Szymanski
quelle

Antworten:

158

Ruby unterstützt nativ Klassenvariablen in Modulen, sodass Sie Klassenvariablen direkt verwenden können und nicht einige Proxy- oder Pseudoklassenvariablen:

module Site
  @@name = "StackOverflow"

  def self.setName(value)
    @@name = value
  end

  def self.name
    @@name
  end
end

Site.name            # => "StackOverflow"
Site.setName("Test")
Site.name            # => "Test"
Coreyward
quelle
4
+1 Eigentlich habe ich gedacht, dass der Begriff 'Klassenvariable' irreführend ist. Klassen sind Sonderfälle von Modulen, und Klassenvariablen können für Module definiert werden. Sie sollten als Modulvariablen bezeichnet werden.
Sawa
3
@sawa: Es ist etwas irreführend, aber es ist das, was Ruby selbst verwendet : defined?(@@foo) => "class variable".
Andrew Grimm
1
Oder sie könnten statische Felder genannt werden. Scheint so zu sein.
Peter Ajtai
@coreyward Hey mein Fehler. Warum werden zwei Klassenvariablen '@@' benötigt? Wird es nicht als Codegeruch angesehen, insbesondere wenn die Klasse um Klassenvariablen erweitert wird? Ich habe dies getestet und festgestellt, dass ich mit einer einzelnen @Instanzvariablen das gleiche Ergebnis erzielen kann. Gibt es einen bestimmten Grund für die Verwendung von Klassenvariablen? Danke für die Antwort.
Fabbb
2
warum die verschiedenen Anrufe am Ende: T.getund T::get?
Intrixius
31

Wenn Sie es nicht innerhalb einer Instanz aufrufen müssen, können Sie einfach eine Instanzvariable innerhalb des Modulkörpers verwenden.

module SomeModule
  module_function
  def param; @param end
  def param= v; @param = v end
end

SomeModule.param
# => nil
SomeModule.param = 1
SomeModule.param
# => 1

Die Instanzvariable gehört @paramdann zu dem Modul SomeModule, das eine Instanz der ModuleKlasse ist.

sawa
quelle
23

Sie können im Modul eine Klasseninstanzvariable festlegen.

module MyModule
   class << self; attr_accessor :var; end
end

MyModule.var = 'this is saved at @var'

MyModule.var    
=> "this is saved at @var"
Orlando
quelle
+1, aber ich möchte nur betonen, dass sich Klasseninstanzvariablen von Klassenvariablen unterscheiden.
Andrew Grimm
4
Ja, total ... und übrigens ... ich empfehle überhaupt nicht, Klassenvariablen zu verwenden. Einige unerwartete Dinge passieren, wenn Sie sie verwenden. In diesem Artikel finden Sie einige Beispiele. oreillynet.com/ruby/blog/2007/01/…
Orlando
8

Sie können den Wert auch innerhalb der Moduldefinition initialisieren:

module MyModule
  class << self
    attr_accessor :my_variable
  end
  self.my_variable = 2 + 2
end

p MyModule.my_variable
Nakilon
quelle