Treatment of class variables in inherited classes 
Author Message
 Treatment of class variables in inherited classes

This question probably has more to do with the fundamentals of OOP than Ruby
specifically, but I'm looking for an explanation of why the behavior of
class variables in inherited classes is the way it is.  Consider:

---
class Box

  def Box.add(k, v)

  end
  def Box.[](knobname)

  end
end

class Crate < Box

end

class Suitcase < Box

end

Crate.add(:d, 4)
Suitcase.add(:d, 5)
puts Crate[:d]        # -> 4 [would be 5 if line 2 were uncommented]
puts Suitcase[:d]     # -> 5
puts Crate[:e]        # -> 2 [would be 3 if line 2 were uncommented]
---

So when a class variable is defined in a parent class, all inherited classes
see the same object.  More specifically, the most recent definition of that
class variable is used, even if it occurred in a subclass.  Yet when a class
variable is not initialized in the parent class, the variable points to
different objects in each class.  This is sensible, but it feels like there
is lacking a "have your cake and eat it too" mechanism that allows for
inherited classes to override/redefine class variables without affecting the
ancestor and sibling classes.

So what are the guiding principles of inheritance that account for this
behavior?  

Thanks,

   - jeff



Sun, 19 Dec 2004 06:40:12 GMT  
 Treatment of class variables in inherited classes
Hello --

Quote:

> This question probably has more to do with the fundamentals of OOP than Ruby
> specifically, but I'm looking for an explanation of why the behavior of
> class variables in inherited classes is the way it is.  Consider:

> ---
> class Box

>   def Box.add(k, v)

>   end

[...]

Quote:
> Crate.add(:d, 4)

Don't you get an "uninitialized class variable" error at that point
(if line 2 is commented out)?

Quote:
> So when a class variable is defined in a parent class, all inherited classes
> see the same object.  More specifically, the most recent definition of that
> class variable is used, even if it occurred in a subclass.  Yet when a class
> variable is not initialized in the parent class, the variable points to
> different objects in each class.  This is sensible, but it feels like there
> is lacking a "have your cake and eat it too" mechanism that allows for
> inherited classes to override/redefine class variables without affecting the
> ancestor and sibling classes.

> So what are the guiding principles of inheritance that account for this
> behavior?

I think you're right that class variables are essentially
per-hierarchy (rather than per class) objects.  Also that if you
define them first in a subclass, this doesn't propagate upward (which
Matz referred to in ruby-talk:19774 as "an error that Ruby does not
detect yet", so I would treat it as deprecated behavior).

If you want real per-class variables, you can create instance
variables for your classes:

  class A

    def A.speak

    end
  end

  class B < A

                # a different object (namely A)
  end

This is different from a class variable, but possibly useful in that
it does provide per-class behavior.

David

--
David Alan Black


Web:  http://pirate.shu.edu/~blackdav



Sun, 19 Dec 2004 07:37:32 GMT  
 Treatment of class variables in inherited classes

Quote:

> > class Box

> >   def Box.add(k, v)

> >   end

> [...]

> > Crate.add(:d, 4)

> Don't you get an "uninitialized class variable" error at that point
> (if line 2 is commented out)?

Actually, the code runs without error on our site installation
of Ruby, which is v1.6.5.  Only Box.add elicits the error with
line 2 commented out, as one would expect.  But on my local build
of v1.6.7 (and 1.7.2), Crate.add does evoke the uninitialized class
variable error.  Kinda makes my whole post moot...  D'oh!  

But I guess my initial instinct -- that the way v1.6.5 behaved
seemed strange -- was in fact justified...

Quote:
> If you want real per-class variables, you can create instance
> variables for your classes:

Thanks, I had never considered that possibility!

Cheers,

  - jeff



Sun, 19 Dec 2004 09:21:42 GMT  
 Treatment of class variables in inherited classes
Hello --

Quote:


> > > class Box

> > >   def Box.add(k, v)

> > >   end

> > [...]

> > > Crate.add(:d, 4)

> > Don't you get an "uninitialized class variable" error at that point
> > (if line 2 is commented out)?

> Actually, the code runs without error on our site installation
> of Ruby, which is v1.6.5.  Only Box.add elicits the error with
> line 2 commented out, as one would expect.  But on my local build
> of v1.6.7 (and 1.7.2), Crate.add does evoke the uninitialized class
> variable error.  Kinda makes my whole post moot...  D'oh!

Hmmm...  I only get the error on 1.6.7... but anyway, I don't think
your post is moot, because the thing with class vars not being/not
being the same object for subclasses still seems to be the case, and
it's good to know about.

Here's a simplified example, just for playing around with:

  # Assignments

  class A

  end

  class B < A

  end

  class A

  end

  # Inspection

  class A

  end

  class B

  end

David

--
David Alan Black


Web:  http://pirate.shu.edu/~blackdav



Sun, 19 Dec 2004 09:47:49 GMT  
 
 [ 4 post ] 

 Relevant Pages 

1. Redefining class that does not inherit with class that does

2. HOWTO restrict multiply inherited class to on sub-class

3. Class variables and class methods

4. Class variables in parent and child classes with the same name

5. Why can't I INITIALIZE a class variable with another class var

6. Non-intuitive treatment of empty list as default parameter value on class method

7. Class variables / global variables / Init variables

8. Class inheriting from a NON CW BaseClass?

9. VO2 DataWindow: Inherit from Class Property

10. Inheriting from the APP Class

11. Inherited Get-class & var

12. use-a-class: inherit or expand?

 

 
Powered by phpBB® Forum Software