N N
N N

Reputation: 1638

How to access instance variable of a module from abother module?

I have module

module SomeModule
  @param = 'Hello'
end

module Reporter
  include SomeModule
  def self.put
    puts @param
  end
end

When I call Reporter::put I get no output, I suppose that Reporter module has no access to instance variable @param. Is there any way to access that variable from Reporter module?

Upvotes: 0

Views: 2164

Answers (3)

Ilya
Ilya

Reputation: 13487

You can use class variable instead of instanse variable

module SomeModule
  @@param = 'Hello'
end

module Reporter
 include SomeModule
 def self.put
  puts @@param
 end
end

Reporter.put prints 123 and returns nil in this case

Upvotes: 1

Jörg W Mittag
Jörg W Mittag

Reputation: 369458

Instance variables are called instance variables, because they belong to objects (aka "instances"). There are two objects in your example: SomeModule and Reporter. Both have their own instance variables. SomeModule has an instance variable named @param and Reporter has an instance variable named @param. Those two instance variables are completely unrelated, even though the have the same name. Imagine the chaos, if every object had to come up with its own names for instance variables!

Is there any way to access that variable from Reporter module?

No. You cannot access instance variables from different objects. An object only has access to its own instance variables.

[Note: it is possible using reflection (e.g. Object#instance_variable_get, BasicObject#instance_eval, or BasicObject#instance_exec), of course. Lots of things are possible using reflection.]

What you can do, however, is create a method that gives you access to read that instance variable. Such a method is called an attribute reader:

module SomeModule
  def self.param; @param end
  @param = 'Hello'
end

module Reporter
  def self.put
    puts SomeModule.param
  end
end

There is even a method which automatically generates such methods for you, it is called Module#attr_reader:

module SomeModule
  class << self; attr_reader :param end
  @param = 'Hello'
end

module Reporter
  def self.put
    puts SomeModule.param
  end
end

If you want to also write to the instance variable, you also need to define a corresponding attribute writer method:

module SomeModule
  class << self
    attr_reader :param

    private

    def param=(param)
      @param = param
    end
  end

  self.param = 'Hello'
end

module Reporter
  def self.put
    puts SomeModule.param
  end
end

There is also a corresponding method named Module#attr_writer which generates an attribute writer method for you:

module SomeModule
  class << self
    attr_reader :param

    private

    attr_writer :param
  end

  self.param = 'Hello'
end

module Reporter
  def self.put
    puts SomeModule.param
  end
end

Upvotes: 0

sawa
sawa

Reputation: 168101

Yes.

SomeModule.instance_variable_get(:@param)

Upvotes: 3

Related Questions