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 called allocate -- this returns an empty instance of the class
  • new then calls initialize on the object returned by allocate, 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.