From: "Mauricio Fernández" Date: 2003-01-23T01:39:03+09:00 Subject: Re: accessors for module instance vars On Thu, Jan 23, 2003 at 12:20:45AM +0900, ahoward wrote: > On Wed, 22 Jan 2003, Mauricio Fern�ndez wrote: > > > > > module M > > > attr_accessor :x > > > @x = 42 > > Doesn't refer to the same thing! > > The former will be an iv. of objects extended with M _or_ > > instanciated from classes that include M. > > The later is a module instance variable, ie, an instance variable > > associated to the 'M' object (that of class Module). > > > end > > > > > > class Foo; include M; end > > > > > > p Foo.new.x # >> nil > > > > Because it's not the same @x! > > > that was my point. This is why we like class instance variables :) The interesting thing about them is that they belong _only_ to that class, not to subclasses like class variables: >> class A >> @@var = 'A::@@var so to speak' >> end => "A::@@var so to speak" >> class B < A >> def a >> @@var >> end >> end => nil >> B.new.a => "A::@@var so to speak" >> class << A; def x= a; @x = a; end; end => nil >> class << A; def x; @x; end; end => nil >> class A >> def interesting >> self.class.x >> end >> end => nil >> a = A.new => # >> A.x= 'belongs only to A' => "belongs only to A" >> a.interesting => "belongs only to A" >> B.new.interesting => nil For one stupid use of this, see below. > > > irb(main):001:0> module M > > irb(main):002:1> class << self; attr_accessor :x; end > > irb(main):003:1> end > > nil > > irb(main):004:0> M.x = 1 > > 1 > > irb(main):005:0> M.x > > 1 > > > didn't know you could do that... And that way you can for instance do the following (but take it with a grain of salt, as I suspect somebody will find some horrible flaw :-P) batsman@tux-chan:/tmp$ cat b.rb module CountInstances def new(*args, &p) @instances ||= 0 @instances += 1 super *args, &p end def instances @instances || 0 end end class A extend CountInstances def initialize puts "Creating instance of #{self.class}" end end class B < A # can have that functionality by subclassing A or using #extend CountInstances end puts "Made #{A.instances} instances of A." puts "Made #{B.instances} instances of B." 2.times { A.new; B.new } 1.times { B.new } puts "Made #{A.instances} instances of A." puts "Made #{B.instances} instances of B." batsman@tux-chan:/tmp$ ruby b.rb Made 0 instances of A. Made 0 instances of B. Creating instance of A Creating instance of B Creating instance of A Creating instance of B Creating instance of B Made 2 instances of A. Made 3 instances of B. It works because B < A but B.class is _not_ derived from A.class :) so the @iv are not the same one depending on initialization order as for normal instance vars. > > > The only ways to access module instance variables are through the > > accessors and instance_eval, AFAIK. > > > AFAIK -> ??? AFAIK, IIRC :) -- _ _ | |__ __ _| |_ ___ _ __ ___ __ _ _ __ | '_ \ / _` | __/ __| '_ ` _ \ / _` | '_ \ | |_) | (_| | |_\__ \ | | | | | (_| | | | | |_.__/ \__,_|\__|___/_| |_| |_|\__,_|_| |_| Running Debian GNU/Linux Sid (unstable) batsman dot geo at yahoo dot com Remember: While root can do most everything, there are certain privileges that only a partner can grant. -- Telsa Gwynne