Utwórz zmienne modułu w Rubim

111

Czy istnieje sposób na utworzenie zmiennej w module w Rubim, która zachowywałaby się podobnie do zmiennej klasy? Rozumiem przez to, że byłby dostępny bez inicjowania instancji modułu, ale można go zmienić (w przeciwieństwie do stałych w modułach).

Mark Szymański
źródło

Odpowiedzi:

158

Ruby natywnie obsługuje zmienne klas w modułach, więc możesz używać zmiennych klas bezpośrednio, a nie niektórych zmiennych proxy lub pseudoklas:

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
źródło
5
+1 Właściwie to myślałem, że termin „zmienna klasy” jest mylący. Klasy są specjalnymi przypadkami modułów, a zmienne klas można definiować w modułach. Powinny nazywać się zmiennymi modułowymi.
sawa
3
@sawa: To jest trochę mylący, ale to, co sama Ruby używa: defined?(@@foo) => "class variable".
Andrew Grimm,
1
Lub można je nazwać polami statycznymi. Wydaje się, że tym właśnie są.
Peter Ajtai
@coreyward Hej, mój błąd. Dlaczego potrzebne są dwie zmienne klasy „@@”? Czy nie jest to uważane za zapach kodu, zwłaszcza jeśli klasa jest rozszerzona o zmienne klasowe? Testowałem to i zdałem sobie sprawę, że mogę uzyskać ten sam wynik z jednej @zmiennej instancji. Czy istnieje konkretny powód używania zmiennych klas? Dziękuję za odpowiedź.
fabbb
2
dlaczego różne wezwania na końcu: T.geti T::get?
intrixius,
31

Jeśli nie musisz wywoływać go z poziomu instancji, możesz po prostu użyć zmiennej instancji w treści modułu.

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

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

Zmienna instancji @parambędzie wtedy należeć do modułu SomeModule, który jest instancją Moduleklasy.

sawa
źródło
23

w module można ustawić zmienną instancji klasy.

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

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

MyModule.var    
=> "this is saved at @var"
Orlando
źródło
+1, ale podkreślę tylko, że zmienne instancji klas różnią się od zmiennych klas.
Andrew Grimm,
4
tak, całkowicie .. i przy okazji ... nie polecam w ogóle używania zmiennych klas .. niektóre nieoczekiwane rzeczy dzieją się, gdy ich używasz .. sprawdź ten artykuł, aby zobaczyć kilka przykładów oreillynet.com/ruby/blog/2007/01/ ...
Orlando
8

Możesz także zainicjować wartość w ramach definicji modułu:

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

p MyModule.my_variable
Nakilon
źródło