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

----------------

--
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

···

On Sat, May 7, 2011 at 10:02 PM, Geometric Patterns < geometric.patterns@gmail.com> wrote:

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

----------------

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

---

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

···

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