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>
If your subclass defines a member variable with the same name as a member variable in its superclass, the variable in the subclass hides the one in the superclass. Thus, the subclass does not inherit the variable from its superclass.
Subclasses do not have access to the private instance variables in a superclass that they extend. Constructors are not inherited.
Explanation: Yes, Module instance variables are present in the class when you would include them inside the class.
Instance variables are not inherited. If a method is written in the subclass with the same name and parameters as one in the parent class, the super class' method is overwritten.
It is well known that Ruby has instance and class variables, just like any Object-Oriented language. They are both widely used, and you can recognize them by the @a and @@a notation respectively.
This existing class is called the base class or superclass, and the new class is called the derived class or sub-class . Let's learn to do all these things in Ruby. Let's start understanding this code by knowing the use of < first. < is used to make a sub-class.
Here we shall introduce a bit of a weird concept: class instance variables. Basically you can recognize them because they look like instance variables, but you'll find them on a class level. They work like a regular class variable, but they differ with those because they are not shared with subclasses.
super will call the constructor of the superclass and will initialize it. So, super (name) will call the constructor of the superclass ( Child ) and will pass 'name' to it and that's it. Rest of the code is simple.
The book (emphasis and addition mine):
If a subclass uses an instance variable with the same name as a[n instance] variable used by one of its ancestors, it will overwrite the value of its ancestor’s variable.
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 sees 42
. This may or may not be intended, hence the warning. It can lead to spectacularly frustrating debugging sessions.
class MyStack
def initialize
@my_array = []
end
def push(item)
@my_array << item
end
end
# Stack class that keeps a list
# of every item ever pushed.
class TrackingStack < MyStack
def initialize
super
@my_array = []
end
def push(item)
super
@my_array << item
end
def all_items_ever_pushed
@my_array
end
end
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:
Subclassing can be risky when you don't control, or are unfamiliar with, the superclass implementation. One reason is because the introduction of an instance variable in the subclass may overwrite the value of a superclass instance variable, leading to unintended behavior.
Instance variables belong to instances, not to classes. The whole idea of "inheritance" doesn't even make sense there, inheritance only applies to classes.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With