5

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?

3 Answers 3

8

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.

Sign up to request clarification or add additional context in comments.

2 Comments

Very good answer, except for one thing: It is totally fine to change the signature of subclasses' constructors. That's because you always know what class you're dealing with when you're instantiating one. Therefore, polymorphy does not need to be considered for constructors. (Notable exception: You might want the same/similar interfaces for constructors when you're doing metaprogramming or you are creating some kind of magic factory.)
You are kind of right about the constructor signature - they are o.k. to change. That doesn't mean it is great to have a completely divergent behaviour of the base and subclass constructor.
3

John Nunemaker has a nice article on the topic.

Comments

2

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.