Question regarding interaction between modules and classes

Hi,

In the code below, is there a way to learn @foo from $bar_one
using $bar_two?

Many thanks in advance!!


#!/usr/bin/ruby -w

module Foo
def setup
@foo = self.object_id
end
def foo
return @foo
end
end

class Bar
include Foo
end

$bar_one = Bar.new
$bar_one.setup
p $bar_one.foo # => 2148224640

$bar_two = Bar.new
p $bar_two.foo # => warning: instance variable @foo not initialized


On Sat, May 7, 2011 at 10:02 PM, Geometric Patterns <
[email protected]> wrote:

#!/usr/bin/ruby -w
class Bar


Posted via http://www.ruby-forum.com/.

Hmm. Okay, first a bunch of thoughts, then some potential solutions.

  1. Variables that begin with the $ sigil are global. For a local
    variable,
    no sigil necessary:
    module Foo
    def setup
    @foo = self.object_id
    end
    def foo
    return @foo
    end
    end
    class Bar
    include Foo
    end
    bar_one = Bar.new
    bar_one.setup
    bar_one.foo # => 2151888860

  2. There is an implicit setup method called “initialize”, it is unusual
    to
    me that you have your own, which you invoke explicitly.
    module Foo
    def initialize
    @foo = self.object_id
    end
    def foo
    return @foo
    end
    end
    class Bar
    include Foo
    end
    Bar.new.foo # => 2151889080

  3. When invoking a method on the current object, self is not necessary
    module Foo
    def initialize
    @foo = object_id
    end
    def foo
    return @foo
    end
    end
    class Bar
    include Foo
    end
    Bar.new.foo # => 2151889080

  4. The last line of a method is automatically returned, no explicit
    “return”
    is necessary
    module Foo
    def initialize
    @foo = object_id
    end
    def foo
    @foo
    end
    end
    class Bar
    include Foo
    end
    Bar.new.foo # => 2151889100

  5. When you have a method which returns an instance variable of the same
    name, that is a less efficient version of “attr_reader :ivar_name”
    module Foo
    def initialize
    @foo = object_id
    end
    attr_reader :foo
    end
    class Bar
    include Foo
    end
    Bar.new.foo # => 2151889260


Okay, now that we’re here, I assume you want to know if bar_two can know
bar_one’s foo
bar_one = Bar.new
bar_two = Bar.new
bar_one.foo # => 2151886760
bar_two.foo # => 2151886740

But it is unclear, because you were initially using global variables,
which
breaks scope, allowing a method like
module Foo
def initialize
@foo = object_id
end
attr_reader :foo
def bar_ones_foo
$bar_one.foo
end
end
class Bar
include Foo
end
$bar_one = Bar.new
$bar_two = Bar.new
$bar_one.foo # => 2151884160
$bar_two.foo # => 2151884140
$bar_two.bar_ones_foo # => 2151884160

Which, seems very strange to me, and doesn’t work if you actually meant
to
have local variables (globals are considered a code smell).

Alternatively, you could have been asking whether they could share the
@foo
ivar, in which case the answer is no, that ivar is unique to whichever
object the method is being called on. However, you could use a class
variable

module Foo
def initialize
@@foo = object_id
end
def foo
@@foo
end
end
class Bar
include Foo
end
bar_one = Bar.new
bar_one.foo # => 2151892400
bar_two = Bar.new
bar_two.foo # => 2151891900
bar_one.foo # => 2151891900
Foo.class_variables # => [:@@foo]

Or, more commonly, an instance variable either on Foo or on Bar
module Foo
class << self
attr_accessor :foo
end
def initialize
Foo.foo = object_id
end
def foo
Foo.foo
end
end
class Bar
include Foo
end
bar_one = Bar.new
bar_one.foo # => 2151891940
bar_two = Bar.new
bar_two.foo # => 2151891440
bar_one.foo # => 2151891440

Although, your wording is pretty vague, this would technically satisfy
the
request
module Foo
def initialize
@foo = object_id
end
attr_reader :foo
def foo_of(other)
other.foo
end
end
class Bar
include Foo
end
bar_one = Bar.new
bar_two = Bar.new
bar_one.foo # => 2151894400
bar_two.foo # => 2151894380
bar_two.foo_of bar_one # => 2151894400

So anyway, hopefully something in there addresses what you are asking.
If
not, you’ll have to give more feedback (ie an interface to access this
information).

Geometric Patterns wrote in post #997317:

Hi,

Don’t EVER use global variables($).

module Foo
def setup
id = self.object_id
puts id

  self.class.class_eval do
     @foo =  id

     def self.foo
        @foo
     end
  end

end

def foo
return self.class.foo
end
end

class Bar
include Foo
end

bar_one = Bar.new
bar_one.setup
p bar_one.foo # => 2148224640

bar_two = Bar.new
p bar_two.foo # => warning: instance variable @foo not initialized

–output:–
83310930
83310930
83310930