Monday, April 16, 2007

Instance Variables, Initialization and Class Hierarchies in Ruby

Perhaps it's because I come from a Java background but I've had a hard time over the last few weeks getting my head around instance variables in Ruby, especially their initialization and how they play in class hierarchies. Hopefully this quick overview of what I've learned saves someone else the pain I had.

I started with a simple hierarchy:

I ran this with the following test case:

And got the following:

Wait a moment, I thought, if ChildClass extends SuperClass, why doesn't it have an @foo instance variable? "It's because we haven't called the SuperClass initializer (with "super") within the ChildClass initializer" said Ruby; "If we do we get this":

This was hard to get my head around. I'd declared the @foo instance variable within the SuperClass so why wasn't it show by inspect? Even simply as having a nil value? "Get over it" Ruby says, "that's how it is. If you want to set the value of something, do it within a method", so I did:

And when I ran the extra bit of test:

I saw that all was well and good:

Two final things, I thought, if nothing happens when I declare the variables did I need them? Also, what if I added another method ("super_foo") to SuperClass which would set @foo to something new would it work from ChildClass? (I kind of knew the answer to this one but just wanted to check). My final version of my class hierarchy looked as follows:

I tested it with this code:

And got this result:

And so that's it, declaring variables is a waste of time outside of a method (let go Java, let go...), use initializers to "initialise" them and use methods to alter them.. All kinda makes sense when you write it out like this doesn't it? ;-)

1 comment:

Esquilax said...

this works quite nicely for inheriting class-instance variables
class C
class << self
attr_accessor :method
class D < C
D.method = "something" => "something"