How to return new instance of subclass while initializing parent class?
The thing is, the return value of initialize
is ignored. here's what happens when you call A.new
:
new
calls a special class method calledallocate
-- this returns an empty instance of the classnew
then callsinitialize
on the object returned byallocate
, and returns the object
To do what you want to do, you need to override new
and make it do what you want:
class A
def self.new(args*)
if(args[0]==1)
B.new(*args[1..-1])
else
C.new(*args[1..-1])
end
end
end
There is something else to consider though. If A
is never really used on its own, you should be using some sort of factory method, or, just a simple if statement. Eg:
def B_or_C(param,args)
(param == 1 ? B : C).new(args)
end
The design really depends on what you are using them for. When you, for example, have a class that could be used to handle multiple versions of something, for example, HTML, you could have a main class HTMLParser
which overrode new
and could return any of its subclasses: HTML1Parser
, HTML2Parser
, HTML3Parser
, HTML4Parser
, and HTML5Parser
.
Note: You have to override the new
method to the default in the sub-classes to prevent infinite looping:
def self.new(args*)
obj=allocate
obj.send(:initialize, *args)
obj
end
You're breaking a fundamental OO principle here -- classes should know nothing about their subclasses. Of course, sometimes principles should be broken, but there's no apparent reason to do it here.
A far better solution is to shift the instantiation logic to a factory method in a separate class. The factory method takes the same arguments as the A's initializer above, and returns an instance of the appropriate class.