In the Chapter 7.3.5 "Inheritance and Instance Variables" of the book "the ruby programing language" says :
Because instance variables have nothing to do with inheritance, it follows that an instance variable used by a subclass cannot “shadow” an instance variable in the superclass. If a subclass uses an instance variable with the same name as a variable used by one of its ancestors, it will overwrite the value of its >ancestor’s variable. This can be done intentionally, to alter the behavior of the ancestor, or it can be done inadvertently. In the latter case, it is almost certain to cause bugs. As with the inheritance of private methods described earlier, this is another reason why it is only safe to extend Ruby classes when you are familiar with (and in control of) the implementation of the superclass.
I had made my own test , but seems instance variables from subclass does NOT affect the superclass
my Ruby version
bob@bob-ruby:~$ ruby --version
ruby 1.9.3p194 (2012-04-20 revision 35410) [i686-linux]
bob@bob-ruby:~$
Below is the code
class Point
attr_accessor :x,:y
def initialize(x,y)
@x,@y=x,y
end
end
class Point3D < Point
attr_accessor :x,:y,:z
def initialize(x,y,z)
@x=x
@y=y
@z=z
end
end
irb(main):052:0> p=Point.new(1,2)
=> #<Point:0x87e8968 @x=1, @y=2>
irb(main):053:0> q=Point3D.new(4,5,6)
=> #<Point3D:0x87e423c @x=4, @y=5, @z=6>
irb(main):054:0> q.x
=> 4
irb(main):055:0> p.x
=> 1
irb(main):056:0>
The book (emphasis and addition mine):
I know you don't have two instances of the same class; we're specifically discussing inheritance.
When a subclass uses an instance variable with the same name as an instance variable used by the superclass, there's a single instance variable. If the subclass changes the value of that instance variable, and the superclass accesses it, it gets the value set by the subclass.
When a subclass is instantiated, it acts "as-if" it's also an instance of the superclass. The way Ruby is implemented means that if the superclass has an instance variable
@foo
, the subclass can access it. This makes a distinction between the subclass's@foo
and the superclass's@foo
meaningless.This is how subclasses may alter superclass behavior: by setting a value the superclass might use. If a subclass sets
@foo = 42
, and a superclass method accesses@foo
, it sees42
. This may or may not be intended, hence the warning. It can lead to spectacularly frustrating debugging sessions.TrackingStack
introduces a bug, because it inadvertently used the same name as the superclass's array used to hold the stack contents. If you weren't familiar with the superclass's implementation, this would cause confusion and bugs until you dug deeply enough to understand where the unintended behavior came from.An instance of the superclass is just that: an instance of the superclass, and it's meaningless to talk about how an instance of the subclass will affect it, because they're completely unrelated.
Here's a rephrasing:
Instance variables belong to instances, not to classes. The whole idea of "inheritance" doesn't even make sense there, inheritance only applies to classes.