I am a programmer, an inventor, a creator of ideas and a dreamer. What are you?

Solution: Nested Classes & Variable Scope (Ruby)

Posted: December 20th, 2009 | Author: Spoofy | Filed under: Articles, Programming | Tags: , , , | Comments Off

I recently began work on a Twitter library for Ruby, some already exist -which I didn’t consider, I wanted to develop a library of my own design which took a very object-oriented approach to accessing Twitter, mostly for practice. Because I wanted an intuitive, and for the lack of a better word, ‘logical’ implementation, I decided to use nested classes.

Ruby nested classes are child classes which are defined within a parent class. Unbeknownst to me, Ruby has some interesting quirks when using nested classes. Take for example, a typical class:

class A
    attr_accessor :var
    def initialize
        @var = "something interesting"
    end
    def tellme
        puts @var
    end
end

Nothing peculiar here, but lets say we want a child class – for all intents and purposes, a namespace, which doesnt inherit from its parent but does exist inside it:

class A
    attr_accessor :var
    def initialize
        @var = "something interesting"
    end
    def say
        puts @var
    end

    class B
        def tellme
            puts @var
        end
    end

end

What we’re doing here is creating a parent class, A; inside that class we have another class B which is a part-of class A, but is not an inherited child. This is an important distinction, because an inherited child would have their own instance variables – what we have here is a class, A which ‘owns’ B. In theory, B should have access to A’s variables.

Heres a usage example, which you might expect to work:

parent = A.new
parent.tellme

child = A::B.new
child.tellme

In theory, we should have the same output, ‘something interesting‘ from calling the tellme method on each class, but no. Instead the child will throw an exception, why? because the instance variable is not visible – it is outside its variable scope. To reiterate: nested classes are outside the variable scope of their parent class.

This is true of class variables and constants. Nested children of a parent class simply do not have access to their parents, unless you provide that functionality programmatically:

class A
    attr_accessor :b, :var
    def initialize
        @var = "something interesting"
        @b = B.new(self)
    end
    def say
        puts @var
    end

    class B
        def initialize(theparent)
            @parent = theparent
        end
        def tellme
            puts @parent.var
        end
    end

end

a = A.new
a.tellme
a.b.tellme


This is the solution I ended up using, hopefully this post will have helped you avoid some of the frustration I went through trying to figure it out.