How can this work?
class A
attr_accessor :name
def initialize params
@name = params[:name]
@collection << B.new
end
end
class开发者_如何学C 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?
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 inA#initialize
is not a good thing, because the base uses the subclass. - You are overwriting the class
B#initialize
with a completely different behaviour thanA#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 theA#initialize
method is never called. You will have to either callsuper(:name => name)
(to run the superclassinitialize
) or you have to assign to@name
directly inB#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.
John Nunemaker has a nice article on the topic.
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
精彩评论