Hunter McMillen
Hunter McMillen

Reputation: 61515

Instance variable access in subclasses

I am hoping that someone could shed some light on the error that I am receiving below. I define an instance variable in the parent class Node and want to access and modify it in the subclass AddSubNode, whenever I try to access @code I receive this error:

'code': undefined method `<<' for nil:NilClass (NoMethodError)

I must be misunderstanding Ruby's inheritance model, but I thought that I could do this.

class Node
  attr_accessor :code

  def initialize
    @code = []
  end
end

class AddSubNode < Node
  def initialize op, l, r
    @op = op
    @l  = l
    @r  = r
  end

  def code
    @code << 1 # error: `code': undefined method `<<' for nil:NilClass (NoMethodError)
    @code
  end

  def to_s
    "#{@l} #{@op} #{@right}"
  end
end

Upvotes: 1

Views: 414

Answers (3)

Arup Rakshit
Arup Rakshit

Reputation: 118261

Here I just tried to give you some visualization to test such scenarios.

class Node
  attr_accessor :code

  def initialize
    @code = []
  end
end

class AddSubNode < Node
  def initialize op, l, r
    @op = op
    @l  = l
    @r  = r
  end

  def code
    @code << 1 # error: `code': undefined method `<<' for nil:NilClass (NoMethodError)
    @code
  end

end

ob = AddSubNode.new(1,2,3)
p ob.instance_variables #=> [:@op, :@l, :@r]
p ob.instance_variable_defined?(:@code) #=> false
p ob.instance_variable_set :@code,[12] #=> [12]
p ob.instance_variable_defined?(:@code) #=> true
p ob.instance_variable_get :@code #=> [12]
p ob.instance_variables #=> [:@op, :@l, :@r, :@code]
p ob.code #=> [12, 1]

Upvotes: 2

rudolph9
rudolph9

Reputation: 8119

When you redefine the initialize method in the subclass, you overwrite the original. Hence the instance variable @code is never initialized, and you code throws an error when you call @code << 1.

Calling super() from the initialize method in your subclass (effectively calling it's parent) or utilizing @code << 1 unless @code.nil? are a few ways to address the error.

Upvotes: 2

tessi
tessi

Reputation: 13574

You need to call the super initializer in the initializer of the subclass.

class AddSubNode < Node
  def initialize op, l, r
    super()
    @op = op
    @l  = l
    @r  = r
  end
...

edit: forgot parenthesis

Upvotes: 4

Related Questions