Inheritance of class variables

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
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 ...
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
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 ...
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. :slight_smile:

----------------------------
Eustáquio "TaQ" Rangel
eustaquiorangel@yahoo.com
http://beam.to/taq
Usuário GNU/Linux no. 224050

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.

I was quite puzzled by this behavior too. So in Rails I use a module called class_inheritable_attributes.rb. It's a bit inconvenient, but I usually wrap all calls to this lib in pretty accessors anyway, so it's not that big of a deal. And very helpful :slight_smile:

http://dev.rubyonrails.com/file/trunk/activesupport/lib/class_inheritable_attributes.rb

···

--
David Heinemeier Hansson,
http://www.basecamphq.com/ -- Web-based Project Management
http://www.rubyonrails.org/ -- Web-application framework for Ruby
http://macromates.com/ -- TextMate: Code and markup editor (OS X)
http://www.loudthinking.com/ -- Broadcasting Brain

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.

it's strange your model :-)))

   class CarBuilder
      def self.inherited(kl)
         kl.instance_eval { @total_of_cars = 0 }
         super
      end
   
      def build
         puts "#{self.class} building another car ..."
         self.class.instance_eval { @total_of_cars += 1 }
      end
   
      def total_of_cars
         "#{self.class} built #{self.class.instance_eval { @total_of_cars }} cars"
      end
   end
   
   class Honda < CarBuilder
   end
   
   class Ford < CarBuilder
   end

Guy Decoux

"Eustaquio Rangel de Oliveira Jr." <eustaquiorangel@yahoo.com> schrieb im
Newsbeitrag news:41D4003E.2060503@yahoo.com...

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.

The short answer is the one that David gave implicite: just don't use
them. IMHO you can safely ignore this language feature without loosing
much but gaining a lot (understandability of code etc.).

As Guy pointed out, you should really be counting the number of cars in
the individual car classes. That's what he's doing with his instance
variable accesses.

I would probably model your example completely different, because Honda
and Ford are really instances of CarBuilder not really sub classes. So
this is the result and suddenly we don't need class vars any more:

class CarBuilder
  attr_reader :name, :total_of_cars

  def initialize(name)
    @name = name
    @total_of_cars = 0
  end

  def build
    puts "#{name} builds another car"
    @total_of_cars += 1
  end
end

h = CarBuilder.new "Honda"
f = CarBuilder.new "Ford"

h.total_of_cars
f.total_of_cars

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

h.total_of_cars
f.total_of_cars

?> h = CarBuilder.new "Honda"
=> #<CarBuilder:0x101865d0 @name="Honda", @total_of_cars=0>

f = CarBuilder.new "Ford"

=> #<CarBuilder:0x10183af8 @name="Ford", @total_of_cars=0>

?> h.total_of_cars
=> 0

f.total_of_cars

=> 0

?> h.build
Honda builds another car
=> 1

h.build

Honda builds another car
=> 2

h.build

Honda builds another car
=> 3

f.build

Ford builds another car
=> 1

?> h.total_of_cars
=> 3

f.total_of_cars

=> 1

Regards

    robert

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
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
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 ...
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
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 ...
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. :slight_smile:

----------------------------
Eustáquio "TaQ" Rangel
eustaquiorangel@yahoo.com
The easiest way to create, record and stream live video - Beings
Usuário GNU/Linux no. 224050

it's strange your model :-)))

Hey Guy!

Thanks, it worked, but too much for a newbie, I need to take a look and
learn with this now. You scared me ahahah, I told you I was a newbie. :slight_smile:
I didn't know that there was "self" on Ruby, for example. :slight_smile:
And what about that instance_eval and inherited there? Ahhh. :slight_smile:

Thanks! :slight_smile:

   class CarBuilder
      def self.inherited(kl)
         kl.instance_eval { @total_of_cars = 0 }
         super
      end

      def build
         puts "#{self.class} building another car ..."
         self.class.instance_eval { @total_of_cars += 1 }
      end

      def total_of_cars
         "#{self.class} built #{self.class.instance_eval { @total_of_cars

}} cars"

      end
   end

   class Honda < CarBuilder
   end

   class Ford < CarBuilder
   end

- ----------------------------
Eustáquio "TaQ" Rangel
eustaquiorangel@yahoo.com

Usuário GNU/Linux no. 224050

Hi!

I would probably model your example completely different, because Honda
and Ford are really instances of CarBuilder not really sub classes. So
this is the result and suddenly we don't need class vars any more:

Thanks for your example! I'm learning about Ruby and taking notes to make a
begginer's tutorial, so while the Guy example really help me to go deep
inside the Ruby depths and think about all that stuff there (wow Guy I was
really amazed with the concept of creating a instance variable there!),
your example is easier for newbies (like me, also) to understand.

Thanks!

- ----------------------------
Eustáquio "TaQ" Rangel
eustaquiorangel@yahoo.com

Usuário GNU/Linux no. 224050

I think I understand all of the code in this thread (see below) except for the
2nd line "attr_reader :name, :total_of_cars". Could you, or someone, explain
this line to me, please?

Also, I tried putting this code into a single *.rb file and I couldn't get any
output. I did get a few warnings, however:

ex.
./1foo.rb:4: warning: parenthesize argument(s) for future version
./1foo.rb:7: warning: parenthesize argument(s) for future version
./1foo.rb:8: warning: parenthesize argument(s) for future version
./1foo.rb:12: warning: parenthesize argument(s) for future version
./1foo.rb:12: warning: parenthesize argument(s) for future version
./1foo.rb:13: warning: parenthesize argument(s) for future version
./1foo.rb:4: undefined method ` ' for CarBuilder:Class (NoMethodError)

I guess the warnings mean that some syntax is being deprecated in later
versions. Assuming that is correct, I still don't see what is generating the
last error.

So, I tried using irb to enter it line by line. However, when I get down to
the where I declare the first instance (h = CarBuilder.new "Honda"), irb
gives me the error, "NameError: uninitialized constant CarBuilder".

Finally, I don't see where you are keeping up with the actual total of cars
built by all manufacturers. So, for practice, I was going to try to extend
this code to handle that. Would the proper way to do that be to declare a
class variable (like @@collective_total = 0) and put it somewhere inside of
the class (like right after the attr_reader . . . line)? Then, inside of the
build method, bump the collective_total?

Thanks,
Darren

···

class CarBuilder
  attr_reader :name, :total_of_cars

  def initialize(name)
    @name = name
    @total_of_cars = 0
  end

  def build
    puts "#{name} builds another car"
    @total_of_cars += 1
  end
end

h = CarBuilder.new "Honda"
f = CarBuilder.new "Ford"

h.total_of_cars
f.total_of_cars

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

h.total_of_cars
f.total_of_cars

?> h = CarBuilder.new "Honda"
=> #<CarBuilder:0x101865d0 @name="Honda", @total_of_cars=0>

>> f = CarBuilder.new "Ford"

=> #<CarBuilder:0x10183af8 @name="Ford", @total_of_cars=0>

?> h.total_of_cars
=> 0

>> f.total_of_cars

=> 0

?> h.build
Honda builds another car
=> 1

>> h.build

Honda builds another car
=> 2

>> h.build

Honda builds another car
=> 3

>> f.build

Ford builds another car
=> 1

?> h.total_of_cars
=> 3

>> f.total_of_cars

=> 1

Regards

    robert

I remember seeing this topic posted to the list a while ago. I'm trying to make a similarly complex model, and its not clear if it is going to work, or if there is a simpler solution for that matter. For the car example I agree that passing the model of the car into the constructor makes sense, but here is my example.

I have a class "ActionSequence" for use with rails that has functions "next" and "previous", I want to pass into the constructor the current action and controller, so this is what ActionSequence looks like:

class ActionSequence
  def initialize(action, controller)
    @action = action
    @controller = controller
  end

  def next
    action = sequence[ sequence.index(@action) + 1 ]
    process_action(action)
  end

  def previous
    action = sequence[ sequence.index(@action) - 1 ]
    process_action(action)
  end

  protected
  def sequence
    self.class.instance_eval { @sequence }
  end

  private
  def process_action(action)
    if self.respond_to?(action, true)
      return self.send(action.id)
    else
      return action
    end
  end
end

And an example of a typical usable child class is as follows:

class OrderSequence < ActionSequence
  @@sequence = ['order_selection',
                             'account_setup',
                             'personal_information']
    def order_selection
        "error_page"
    end
end

So before anything is done, the action will initialize the sequence to the right spot, and inside my "view" I can call next and previous as a helper and it refers to OrderSequence.next and OrderSequence.previous, which traverses the @@sequence class variable, and it will check for a callback function for additional logic.

But this doens't work. I haven't been able to figure very much out about how instance_eval works on Class objects. If anybody can offer any advise, or if anybody has done a similar sort of thing, I'd appreciate some input.

-Jeff

···

----- Original Message ----- From: "Robert Klemme" <bob.news@gmx.net>
Newsgroups: comp.lang.ruby
To: "ruby-talk ML" <ruby-talk@ruby-lang.org>
Sent: Thursday, December 30, 2004 10:16 AM
Subject: Re: Inheritance of class variables

"Eustaquio Rangel de Oliveira Jr." <eustaquiorangel@yahoo.com> schrieb im
Newsbeitrag news:41D4003E.2060503@yahoo.com...

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.

The short answer is the one that David gave implicite: just don't use
them. IMHO you can safely ignore this language feature without loosing
much but gaining a lot (understandability of code etc.).

As Guy pointed out, you should really be counting the number of cars in
the individual car classes. That's what he's doing with his instance
variable accesses.

I would probably model your example completely different, because Honda
and Ford are really instances of CarBuilder not really sub classes. So
this is the result and suddenly we don't need class vars any more:

class CarBuilder
attr_reader :name, :total_of_cars

def initialize(name)
   @name = name
   @total_of_cars = 0
end

def build
   puts "#{name} builds another car"
   @total_of_cars += 1
end
end

h = CarBuilder.new "Honda"
f = CarBuilder.new "Ford"

h.total_of_cars
f.total_of_cars

h.build
f.build

h.total_of_cars
f.total_of_cars

?> h = CarBuilder.new "Honda"
=> #<CarBuilder:0x101865d0 @name="Honda", @total_of_cars=0>

f = CarBuilder.new "Ford"

=> #<CarBuilder:0x10183af8 @name="Ford", @total_of_cars=0>

?> h.total_of_cars
=> 0

f.total_of_cars

=> 0

?> h.build
Honda builds another car
=> 1

h.build

Honda builds another car
=> 2

h.build

Honda builds another car
=> 3

f.build

Ford builds another car
=> 1

?> h.total_of_cars
=> 3

f.total_of_cars

=> 1

Regards

   robert

Eustaquio Rangel de Oliveira Jr. wrote:

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

> it's strange your model :-)))

Hey Guy!

Thanks, it worked, but too much for a newbie, I need to take a look and
learn with this now. You scared me ahahah, I told you I was a newbie. :slight_smile:

No, you scared not only becuase you are newbie, but because you were answered by Guy :slight_smile:

Keep working on Ruby for many more years and he will still scare you :wink:

I didn't know that there was "self" on Ruby, for example. :slight_smile:
And what about that instance_eval and inherited there? Ahhh. :slight_smile:

Thanks! :slight_smile:

Have fun !
-- shanko

···

>
> class CarBuilder
> def self.inherited(kl)
> kl.instance_eval { @total_of_cars = 0 }
> super
> end
>
> def build
> puts "#{self.class} building another car ..."
> self.class.instance_eval { @total_of_cars += 1 }
> end
>
> def total_of_cars
> "#{self.class} built #{self.class.instance_eval { @total_of_cars
}} cars"
> end
> end
>
> class Honda < CarBuilder
> end
>
> class Ford < CarBuilder
> end

- ----------------------------
Eustáquio "TaQ" Rangel
eustaquiorangel@yahoo.com
The easiest way to create, record and stream live video - Beings
Usuário GNU/Linux no. 224050
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.6 (GNU/Linux)
Comment: Using GnuPG with Thunderbird - http://enigmail.mozdev.org

iD8DBQFB1Aokb6UiZnhJiLsRAs0oAKC2uZAh8MB2amkV96JtIqa3vgQ6xACfUn3Y
EV+7wuTrWDyD8tq1LxBaV9w=
=DDYu
-----END PGP SIGNATURE-----

"Eustaquio Rangel de Oliveira Jr." <eustaquiorangel@yahoo.com> schrieb im Newsbeitrag news:41D43A27.6070108@yahoo.com...

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Hi!

> I would probably model your example completely different, because Honda
> and Ford are really instances of CarBuilder not really sub classes. So
> this is the result and suddenly we don't need class vars any more:

Thanks for your example! I'm learning about Ruby and taking notes to make a
begginer's tutorial, so while the Guy example really help me to go deep
inside the Ruby depths and think about all that stuff there (wow Guy I was
really amazed with the concept of creating a instance variable there!),
your example is easier for newbies (like me, also) to understand.

But please note that my point was not so much about Ruby but about OO modeling. Honda, Ford and others are really instances of CarBuilder. That's why you just need one class.

Of course, if you had different kinds of CarBuilders with different capabilities (say LorryCarBuilder, SedanCarbuilder, SUVCarBuilder and SportsWagonCarBuilder) you would need several classes; but even then Ford would be an instance of LorryCarBuilder (or whatever) which normally would inherit CarBuilder.

Thanks!

You're welcome! I'm glad I could be of any help.

Regards

    robert

"darren" <rubylang@usmstudent.com> schrieb im Newsbeitrag news:200501011014.19101.rubylang@usmstudent.com...

I think I understand all of the code in this thread (see below) except for the
2nd line "attr_reader :name, :total_of_cars". Could you, or someone, explain
this line to me, please?

Also, I tried putting this code into a single *.rb file and I couldn't get any
output. I did get a few warnings, however:

ex.
/1foo.rb:4: warning: parenthesize argument(s) for future version
/1foo.rb:7: warning: parenthesize argument(s) for future version
/1foo.rb:8: warning: parenthesize argument(s) for future version
/1foo.rb:12: warning: parenthesize argument(s) for future version
/1foo.rb:13: warning: parenthesize argument(s) for future version
/1foo.rb:4: undefined method ` ' for CarBuilder:Class (NoMethodError)

I guess the warnings mean that some syntax is being deprecated in later
versions. Assuming that is correct, I still don't see what is generating the
last error.

Which version of Ruby are you using? I tested with 1.8.1 and didn't see any of those errors. Maybe it's a copy and paste problem from the mail? Line endings could be a reason.

So, I tried using irb to enter it line by line. However, when I get down to
the where I declare the first instance (h = CarBuilder.new "Honda"), irb
gives me the error, "NameError: uninitialized constant CarBuilder".

Works for me:

$ irbs

class CarBuilder
  attr_reader :name, :total_of_cars

?> def initialize(name)

    @name = name
    @total_of_cars = 0
  end

?> def build

    puts "#{name} builds another car"
    @total_of_cars += 1
  end
end

=> nil

?> h = CarBuilder.new "Honda"
=> #<CarBuilder:0x100ccce0 @name="Honda", @total_of_cars=0>

Finally, I don't see where you are keeping up with the actual total of cars
built by all manufacturers.

My example code doesn't.

So, for practice, I was going to try to extend
this code to handle that. Would the proper way to do that be to declare a
class variable (like @@collective_total = 0) and put it somewhere inside of
the class (like right after the attr_reader . . . line)? Then, inside of the
build method, bump the collective_total?

I would not use a class var. Rather use an instance var of the class.

You could also query all instances which reduces redundancy and thus error likelyness:

total = 0; ObjectSpace.each_object(CarBuilder) {|o| total += o.total_of_cars}; total

=> 0

h.build

Honda builds another car
=> 1

h.build

Honda builds another car
=> 2

h.build

Honda builds another car
=> 3

total = 0; ObjectSpace.each_object(CarBuilder) {|o| total += o.total_of_cars}; total

=> 3

Of course, if you need the number of all cars often then it's more efficient to introduce redundancy and have a total of all car makers available.

Regards

    robert

You probably make confusion between class variable and class instance
variable

  def sequence
    self.class.instance_eval { @sequence }

this is a class instance variable.

class OrderSequence < ActionSequence
  @@sequence = ['order_selection',
                             'account_setup',
                             'personal_information']

this is a class variable.

Try it with

   class OrderSequence < ActionSequence
      @sequence = ['order_selection',
         'account_setup',
         'personal_information']

      def order_selection
         "error_page"
      end
   end

Guy Decoux

Hi!

No, you scared not only becuase you are newbie, but because you were
answered by Guy :slight_smile:
Keep working on Ruby for many more years and he will still scare you :wink:

So he's kind of a Ruby boogeyman??? :smiley:
Just kidding. :smiley:
Thanks for your help (my brain is still hot here).

- ----------------------------
Eustáquio "TaQ" Rangel
eustaquiorangel@yahoo.com

Usuário GNU/Linux no. 224050

I'm using 1.8.1, too. I just retyped it in and it's working now. Guess it
Must have been a hidden EOL of or something.

I just ran across the explanation for att_reader in my Ruby book. Cool
shortcut.

Thanks,
Darren

···

On Sunday 02 January 2005 4:11 am, Robert Klemme wrote:

"darren" <rubylang@usmstudent.com> schrieb im Newsbeitrag
news:200501011014.19101.rubylang@usmstudent.com...

Which version of Ruby are you using? I tested with 1.8.1 and didn't see
any of those errors. Maybe it's a copy and paste problem from the mail?
Line endings could be a reason.

Eustaquio Rangel de Oliveira Jr. wrote:

Thanks for your help (my brain is still hot here).

My brain is not here either (I'm fighting a headache) and I didn't
carefully read the example code, but maybe the following will help (and
maybe it's way off base).

Ruby allows you to have class variables and instance variables. If you
have a class like cars (I didn't read the example closely at all) and
instances for Ford, Honda, ..., only one class variable will exist but
instance variables will exist for Ford, Honda, .... Thus, if, for
example, you want a total over all cars, you (with suitable coding) want
to use the class variable. If you want separate totals for Ford, Honda,
..., you want to use instance variables.

Going even further out on a limb (I'm a Ruby newbie too (and <sad
attempt at a joke warning>and if you don't like my ideas, you could say
goodbye, Ruby newbie, and even write a song about it</sad attempt at a
joke warning>)), IIRC, a class variable is prefixed with @@, and
something else (maybe instance variables?) are prefixed with @.

Randy Kramer

Hi!

Going even further out on a limb (I'm a Ruby newbie too (and <sad
attempt at a joke warning>and if you don't like my ideas, you could say
goodbye, Ruby newbie, and even write a song about it</sad attempt at a
joke warning>)), IIRC, a class variable is prefixed with @@, and
something else (maybe instance variables?) are prefixed with @.

No need to say goodbye or write a song ahahah. :slight_smile:
After all, I play on a Thrash Metal band, and we'are not so good on sad
songs ehehe. :slight_smile:

Best regards,

- ----------------------------
Eustáquio "TaQ" Rangel
eustaquiorangel@yahoo.com
http://beam.to/taq
Usuário GNU/Linux no. 224050

Eustaquio Rangel de Oliveira Jr. wrote:

:slight_smile:

:slight_smile: