18

Can someone explain how a class can access the instance variables of its superclass and how that is not inheritance? I'm talking about 'The Ruby Programming Language' and the example

class Point
  def initialize(x,y) # Initialize method 
     @x,@y = x, y      # Sets initial values for instance variables
  end

end

class Point3D < Point
 def initialize(x,y,z)
   super(x,y)
   @z = z
 end
 def to_s
   "(#@x, #@y, #@z)"  # Variables @x and @y inherited?
 end
end

Point3D.new(1,2,3).to_s => "(1, 2, 3)"

How can class Point3D access x and y inside to_s if they're not inherited? The book says:

"The reason that they sometimes appear to be inherited is that instance variables are created by the methods that first assign values to them, and those methods are often inherited or chained."

but I can't figure out what it really means.

sawa
  • 165,429
  • 45
  • 277
  • 381
Zed
  • 5,683
  • 11
  • 49
  • 81

4 Answers4

15

You are right, the book is wrong, or at least poorly worded


I would argue that the book is simply wrong, or at best, it's making a quite muddy explanation.

In all OO languages, the superclass and derived class don't have separate objects. When you create an instance of the derived class, it is also an instance of the superclass. There is one object and it is both classes at once.

Since there is only one object, there is only one set of instance variables.

This is the same as all other OO systems. The weird argument that book makes about how it just matters which method is run and how the methods themselves are what are really inherited does not add much in the way of clarity.

The problem with the terminology is that, sure, in a dynamically typed system there is no declaration in the first place, and so certainly the definition of the subclass doesn't inherit any field declarations ... because of course there aren't any. But just because there are no types to inherit doesn't make the opposite statement ("instance variables are not inherited") any more true, and it adds quite a bit of confusion because it implies that somehow the parent would have different instance variables, which is the nonsensical result of trying to talk about the objects the way they do.

DigitalRoss
  • 143,651
  • 25
  • 248
  • 329
  • 1
    Thanks.I made some tests and concluded the following: If parent class constructor is called and it defines instance variables, those variables will be accessible to derived class, and can be altered through derived class, or through parent class.That's what I understand right now, I'll have probably bigger picture with more experience. – Zed Nov 16 '12 at 22:26
  • 3
    As you have said, in the case where constructor(initialize) is overridden in child class, the instance variable in parent class constructor(initialize) wont be available, because parent class constructor is not executed for creating the child class object(it has its own initialize method). Now case 2, when we don't override the initialize method, in this case the parent class constructor is executed and new child object is created. This makes all the instance variable in parent class initialize method available to the child class object and its methods. – RubyMiner Feb 03 '15 at 14:46
7

super(x,y) calls the constructor of the base class, which is the initialize method. If you take super(x,y) out, then the variables @x and @y won't appear in the derived class.

Candide
  • 30,469
  • 8
  • 53
  • 60
  • Sure, but the OP's question is a bit more about the nature of OO and his reaction to the muddy text he is reading. – DigitalRoss Nov 17 '12 at 16:26
1

It's confusingly worded. @x, @y, and @z are all instance variables on that Point3D instance. If that super(x,y) wasn't there, the Point3D instance would not have a @x or @y.

Catnapper
  • 1,875
  • 10
  • 12
  • Ahh, be careful. "The `Point3D` instance" is also "The `Point` instance", and if `super(x,y)` *"wasn't there"* then `Point` would not have an `@x` or `@y` either. – DigitalRoss Jul 11 '16 at 17:38
0

You can compare these two examples.

example 1: it seems B inherit @i from A.

class A
  def initialize()
    @i = "ok"
  end
end

class B < A
  def print_i()
    p(@i)
  end
end

B.new().print_i()   # Shows "ok"

example 2: if B has its own initialize(), it cannot find @i.

class A
  def initialize()
    @i = "ok"
  end
end

class B < A
  def initialize()
  end

  def print_i()
    p(@i)
  end
end

B.new().print_i()   # nil, print nothing

class B's @i in example 1, is actually created implicitly by A#initialize() when you invoke B.new().

In your case, @x and @y in Point3D is actually created by Point#initialize(), not inherited from Point

mCY
  • 2,731
  • 7
  • 25
  • 43