Hi all,

Personally I never use class variables, since I consider them  
inherently broken. Although I have no constructive opinion of how they  
_should_ function, I know after trying several times, that they simply  
do not work the way I want to use them. Instead I sometimes use class  
_instance_ variables, that is instance variables on the class object.  
The idea is exactly the same as Guy's, but with lazy initialization, so  
I get to skip some of the instance_evals. Thus my version of the code  
would look like...

------------------------------------------------------------------------
class CarBuilder
     def initialize(name)
         @name = name
     end

     def self.total_of_cars
         @total_of_cars or 0
     end

     def self.increase_total
       @total_of_cars = (@total_of_cars or 0) + 1
     end

    def build
       puts "#{@name} building another car ..."
       self.class.increase_total
    end

    def total_of_cars
       "#{@name} built #{self.class.total_of_cars} cars"
    end
end

class Honda < CarBuilder
    def initialize
       super("Honda")
    end
end

class Ford < CarBuilder
    def initialize
       super("Ford")
    end
end

h = Honda.new
f = Ford.new

puts h.total_of_cars
puts f.total_of_cars

h.build
h.build
h.build
f.build

puts h.total_of_cars
puts f.total_of_cars
------------------------------------------------------------------------


The output then shows 3 Hondas and 1 Ford. Of course, this is a simple  
special case of a factory object, the class object being the factory.  
Thus I would probably write the code slightly different, putting the  
#total_of_cars method on the class and making #build a synonym of #new,  
which would seem to me the saner approach.

Just my two euro-cents.
/Curne
--
Mailing lists confuse me. Often I don't recognize my own posts and set  
about writing a flaming reply where I violently disagree.  
[curne / curnomatic.dk]


On 2004 Dec, 30, at 14:17, Eustaquio Rangel de Oliveira Jr. wrote:

> Hello there.
>
> I was talking with chris2 and matju on the irc channel and they gave  
> me good explanation about this point, but I'd like to share it with  
> you and discuss something about it.
>
> I was asking about if, when defined on a parent class, a class  
> variable overwrites the class variables with the same name on it's  
> children.
>
> For example:
>
> ----------------------------------------------------------------------- 
> -
> class CarBuilder
>    @@total_of_cars=0
>    def initialize(name)
>       @name = name
>    end	
>    def build
>       puts "#{@name} building another car ..."
>       @@total_of_cars +=1
>    end
>    def total_of_cars
>       "#{@name} built #{@@total_of_cars} cars"
>    end
> end
>
> class Honda < CarBuilder
>    @@total_of_cars=0
>    def initialize
>       super("Honda")
>    end
> end
>
> class Ford < CarBuilder
>    @@total_of_cars=0
>    def initialize
>       super("Ford")
>    end
> end
>
> h = Honda::new
> f = Ford::new
>
> puts h.total_of_cars
> puts f.total_of_cars
>
> h.build
> h.build
> h.build
> f.build
>
> puts h.total_of_cars
> puts f.total_of_cars
> ----------------------------------------------------------------------- 
> -
>
> Running this code we have:
>
> ----------------------------------------------------------------------- 
> -
> Honda built 0 cars
> Ford built 0 cars
> Honda building another car ...
> Honda building another car ...
> Honda building another car ...
> Ford building another car ...
> Honda built 4 cars
> Ford built 4 cars
> ----------------------------------------------------------------------- 
> -
>
> So, there is a mistake here. Honda built 3 cars and Ford 1, and not 4  
> for Honda and 4 for Ford. They are sharing the parent class variable,  
> not matter if it was defined on the children also.
>
> Matsu told me that who came first is the boss, so if @@total_of_cars  
> was defined on the parent, not matter what, all the other children  
> will refer to it. I can live with that making some hacks ehehe but let  
> me see:
>
> ----------------------------------------------------------------------- 
> -
> class CarBuilder
>    def initialize(name)
>       @name = name
>    end	
>    def build
>       puts "#{@name} building another car ..."
>       increase
>    end
>    def increase
>    end
> end
>
> class Honda < CarBuilder
>    @@total_of_cars=0
>    def initialize
>       super("Honda")
>    end
>    def increase
>       @@total_of_cars +=1
>    end
>    def total_of_cars
>       "#{@name} built #{@@total_of_cars} cars"
>    end
> end
>
> class Ford < CarBuilder
>    @@total_of_cars=0
>    def initialize
>       super("Ford")
>    end
>    def increase
>       @@total_of_cars +=1
>    end
>    def total_of_cars
>       "#{@name} built #{@@total_of_cars} cars"
>    end
> end
>
> h = Honda::new
> f = Ford::new
>
> puts h.total_of_cars
> puts f.total_of_cars
>
> h.build
> h.build
> h.build
> f.build
>
> puts h.total_of_cars
> puts f.total_of_cars
> ----------------------------------------------------------------------- 
> -
>
> Running it I got:
>
> ----------------------------------------------------------------------- 
> -
> Honda built 0 cars
> Ford built 0 cars
> Honda building another car ...
> Honda building another car ...
> Honda building another car ...
> Ford building another car ...
> Honda built 3 cars
> Ford built 1 cars
> ----------------------------------------------------------------------- 
> -
>
> That is the correct behaviour.
> But let check what I changed there on the code:
>
> - I removed @@total_of_cars from CarBuilder, and put it on *each*  
> child class (there was one row of code, now there is two - or more, if  
> more children), and could be a problem if I miss the point on some  
> child class and forget to declare that variable there).
>
> - On the CarBuilder, I create an empty method there called "increase"  
> just to call it on the "build" method (that I want the children  
> inherit it's funcionality). Two more rows there.
>
> - I also removed the total_of_cars method from CarBuilder, but needed  
> to write it on each children. 3 rows less on the parent, but 3 more on  
> each child.
>
> - Also on the children I needed to write the increase method, 3 more  
> rows on each child.
>
> Sorry if I'm missing some point here, because I'm a Ruby newbie, but  
> is that correct? I mean, seems that we need to write more code with  
> this kind of behaviour.
>
> And if we forget to implement some of the needed methods or the  
> @@total_of_cars on each CarBuilder child (CarBuilder could have a lot  
> of other methods that I could want to inherit also!), it could not  
> work normally.
>
> On another point, if all this methods and variables could be inherited  
> from the parent class, will be no problem.
>
> I don't really know if there is a strong and well-defined OOP concept  
> on the fact that a child cannot overwrite it's parent class variables,  
> but could you
>
> - Tell me if there is some kind of OOP concept like that and
> - Tell me if the way I made the code, even with more lines, is the  
> correct and more efficient way to control how many cars each  
> CarBuilder child made?
>
> Thanks for your attention. :-)
>
> ----------------------------
> EustŠ“uio "TaQ" Rangel
> eustaquiorangel / yahoo.com
> http://beam.to/taq
> UsuŠ”io GNU/Linux no. 224050
>
>
>