Bruno Antunes
Bruno Antunes

Reputation: 2262

Access parent class instance variable

How can this work?

class A
  attr_accessor :name

  def initialize params
    @name = params[:name]
    @collection << B.new 
  end
end

class B < A
  def initialize
    @my_name = lookup_something(<parent.name>)
  end
end

Basically, I need a value from the parent class to use in a lookup on the child class, but I don't want to pass it explicitly if there's a better way. Is the instance var of the parent totally inaccessible in the child class? Or is this just poor hierarchy design?

Upvotes: 5

Views: 18320

Answers (3)

averell
averell

Reputation: 3772

I don't really know what you are trying to do here - all the code you posted works on instance variables. Instance variables are per-object, not per class, so I don't know what you mean when you say "I need a value from the parent class".

There are several things that I note with your code:

  • Base classes should never be aware of subclasses. So creating B objects in A#initialize is not a good thing, because the base uses the subclass.
  • You are overwriting the class B#initialize with a completely different behaviour than A#initialize. You even change the parameter list. Not a very good thing either. An object of a subclass should behave in the same way as an object of its superclass.
  • When you call B.new('myname') the variable @name is never assigned, because the A#initialize method is never called. You will have to either call super(:name => name) (to run the superclass initialize) or you have to assign to @name directly in B#initialize
  • Once @name is defined, all your instance methods can use its value. Including the ones that are defined in the parent/superclass.

Let me say I'm not quite sure why you are using inheritance here, I have the feeling that it is not what you want. If you have two classes for two different things, there should never be inheritance involved. If you want to re-use code, either have a look at Ruby's mixin feature, or compose your complex objects of several "smaller" objects that have the behaviour you want to re-use.

Upvotes: 8

Vojto
Vojto

Reputation: 6949

John Nunemaker has a nice article on the topic.

Upvotes: 3

dbyrne
dbyrne

Reputation: 61011

What is the reason you want B to inherit from A? Unless you have another reason, the right way to design this would be to simply take the name as a parameter for B's constructor and ditch the inheritance.

class A
  attr_accessor :name

  def initialize params
    @name = params[:name]
    @collection << B.new(@name)
  end
end

class B
  def initialize name
    @my_name = lookup_something(@name)
  end
end

Upvotes: 2

Related Questions