What happens to instance variables in modules when they are extended into classes

Hi,

Please take a look at the code pasted at this URL (I will include the
code in the body of this message (below) for future readers, but the
rafb.net post will give readers for the next 24 hours something better
to look at): http://rafb.net/p/9MkY3H79.html

Why is it that an instance method of the module gets mixed into the
class, but instance variables of the module do not get mixed in?

Whats the best strategy for writing instance methods in a module that
depend on some state in the mixee?

Thanks very much,
Mike.

And now here is the code snippet:

module M
  @module_instance_variable = 'miv'

  def module_instance_method
    @module_instance_variable
  end
end

class C
  extend M
end

puts "Is module_instance_method in the methods of the class?
#{C.methods.include?('module_instance_method')}"
puts "Is @module_instance_variable in the instance variables of the
class? #{C.instance_variables.include?('@module_instance_variable')}"
puts "Is @module_instance_variable in the class variables of the
class? #{C.class_variables.include?('@module_instance_variable')}"

Presumably you understand why the following code prints 'nil':

class C
  @foo = "hello"

  def bar
    puts @foo
  end
end
C.new.bar

So I'm not sure what you're trying to achieve with your code snippet. Do you
want @module_instance_variable to be an instance variable of module M, or an
instance variable of class C, or an instance variable of instances of class
C?

What you have at the moment is an instance variable of M, as shown by:

puts M.module_eval { @module_instance_variable }

If you want to set up instance variables of class C itself (remembering that
many different C's may each extend M), then one approach is

module M
  def self.extended(obj)
    puts "hello!"
    obj.instance_eval { @miv = "miv" }
  end
end

class C
  extend M
end

puts C.instance_variables

HTH,

Brian.

···

On Tue, Apr 10, 2007 at 11:25:06PM +0900, me@mikehogan.net wrote:

Why is it that an instance method of the module gets mixed into the
class, but instance variables of the module do not get mixed in?

Whats the best strategy for writing instance methods in a module that
depend on some state in the mixee?

Thanks very much,
Mike.

And now here is the code snippet:

module M
  @module_instance_variable = 'miv'

  def module_instance_method
    @module_instance_variable
  end
end

class C
  extend M
end

You know, there's a downside to your e-mail addy, me@mikehogan.net. In
Gmail it says the thread was started by me and I go, oh, hmm, I don't
remember posting that. Was I in a hypnotic trance? Was I possessed by
demons? Did I post it a long long time ago?

(Fortunately the inevitable identity crisis resolves itself peacefully
and uneventfully.)

···

--
Giles Bowkett
http://www.gilesgoatboy.org


http://giles.tumblr.com/

Ok - yes thats twigged it for me. Thanks very much Brian.

Mike

···

On Apr 10, 9:33 pm, Brian Candler <B.Cand...@pobox.com> wrote:

On Tue, Apr 10, 2007 at 11:25:06PM +0900, m...@mikehogan.net wrote:
> Why is it that an instance method of the module gets mixed into the
> class, but instance variables of the module do not get mixed in?

> Whats the best strategy for writing instance methods in a module that
> depend on some state in the mixee?

> Thanks very much,
> Mike.

> And now here is the code snippet:

> module M
> @module_instance_variable = 'miv'

> def module_instance_method
> @module_instance_variable
> end
> end

> class C
> extend M
> end

Presumably you understand why the following code prints 'nil':

class C
  @foo = "hello"

  def bar
    puts @foo
  end
end
C.new.bar

So I'm not sure what you're trying to achieve with your code snippet. Do you
want @module_instance_variable to be an instance variable of module M, or an
instance variable of class C, or an instance variable of instances of class
C?

What you have at the moment is an instance variable of M, as shown by:

puts M.module_eval { @module_instance_variable }

If you want to set up instance variables of class C itself (remembering that
many different C's may each extend M), then one approach is

module M
  def self.extended(obj)
    puts "hello!"
    obj.instance_eval { @miv = "miv" }
  end
end

class C
  extend M
end

puts C.instance_variables

HTH,

Brian.