Frage Wie kann ich die Instanzvariablen eines Moduls in Ruby initialisieren?


Ich habe einige Module, in denen ich Instanzvariablen verwenden möchte. Ich initialisiere sie gerade wie folgt:

module MyModule
  def self.method_a(param)
    @var ||= 0
    # other logic goes here
  end
end

Ich könnte auch eine init-Methode aufrufen, um sie zu initialisieren:

def init
  @var = 0
end

aber das würde bedeuten, dass ich daran denken muss, es immer zu nennen.

Gibt es einen besseren Weg, dies zu tun?


75
2018-03-30 17:56


Ursprung


Antworten:


Initialisieren Sie sie in der Moduldefinition.

module MyModule
  # self here is MyModule
  @species = "frog"
  @color = "red polka-dotted"
  @log = []

  def self.log(msg)
    # self here is still MyModule, so the instance variables are still available
    @log << msg
  end
  def self.show_log
    puts @log.map { |m| "A #@color #@species says #{m.inspect}" }
  end
end

MyModule.log "I like cheese."
MyModule.log "There's no mop!"
MyModule.show_log #=> A red polka-dotted frog says "I like cheese."
                  #   A red polka-dotted frog says "There's no mop!"

Dadurch werden die Instanzvariablen festgelegt, wenn das Modul definiert ist. Denken Sie daran, dass Sie das Modul später erneut öffnen können, um weitere Instanzvariablen und Methodendefinitionen hinzuzufügen. oder um bestehende neu zu definieren:

# continued from above...
module MyModule
  @verb = "shouts"
  def self.show_log
    puts @log.map { |m| "A #@color #@species #@verb #{m.inspect}" }
  end
end
MyModule.log "What's going on?"
MyModule.show_log #=> A red polka-dotted frog shouts "I like cheese."
                  #   A red polka-dotted frog shouts "There's no mop!"
                  #   A red polka-dotted frog shouts "What's going on?"

101
2018-03-30 19:42



Sie können verwenden:

def init(var=0)
 @var = var
end

Und es wird standardmäßig auf 0 gesetzt, wenn Sie nichts übergeben.

Wenn Sie es nicht jedes Mal aufrufen müssen, können Sie Folgendes verwenden:

module AppConfiguration
   mattr_accessor :google_api_key
   self.google_api_key = "123456789"
...

end

6
2018-03-30 18:03



Für eine Klasse würde ich Folgendes sagen, da die Initialisierung immer dann aufgerufen wird, wenn Sie eine neue Instanz der Klasse neu aufrufen.

def initialize
   @var = 0
end

von Praktischer Rubin:

Es fährt fort zu sagen, dass ein Modul ist   initialize wird aufgerufen, wenn ein   einschließlich der Initialisierungsaufrufe der Klasse   super, aber erwähnt das nicht   ist eine Folge davon, wie super funktioniert   überall, keine spezielle Handhabung für   initialisieren. (Warum könnte man annehmen   initialisiert bekommt spezielle Handhabung?   Weil es spezielle Handhabung mit bekommt   in Bezug auf Sichtbarkeit. Sonderfälle   Verwirrung schaffen.)


2
2018-03-30 18:12



Offensichtlich ist es eine schlechte Form, Instanzvariablen in einem Modul in Ruby zu initialisieren. (Aus Gründen, die ich nicht vollständig verstehe, aber in Bezug auf die Reihenfolge, in der Dinge instanziiert werden.)

Es scheint, dass Best Practices die Verwendung von Accessoren mit fauler Initialisierung sind:

module MyModule
  def var
    @var ||= 0 
  end
end

Dann benutze var als der Getter für @var.


2
2018-04-15 12:14



Ich habe eine ähnliche Antwort gegeben Fragekannst du einstellen Klasseninstanzvariablen Dies tun

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

MyModule.var
=> nil

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

MyModule.var    
=> "this is saved at @var"

1
2018-01-09 05:13