How can I change the return value of a class constructor in Ruby?

By definition, constructors are meant to return a newly created object of the class they are a member of, so, no you should not override this behavior.

Besides, in Ruby, new calls initialize somewhere within its method body, and its return value is ignored, so either way the value you return from initialize will not be returned from new.

With that said, I think that in your case, you might want to create a factory method that will return different Foo objects based on arguments passed to the factory method:

class Foo
  def self.factory(arg = nil)
    return arg if arg.kind_of? Foo
    Foo.new
  end
end
foo = Foo.factory
bar = Foo.factory(foo)

assert_equal foo, bar #passes

def Foo.new(arg=nil)
  arg || super
end

initialize is called by new which ignores its return value. Basically the default new method looks like this (except that it's implemented in C, not in ruby):

class Class
  def new(*args, &blk)
    o = allocate
    o.send(:initialize, *args, &blk)
    o
  end
end

So the newly allocated object is returned either way, no matter what you do in initialize. The only way to change that is overriding the new method, for example like this:

class Foo
  def self.new(arg=nil)
    if arg
      return arg
    else
      super
    end
  end
end

However I'd strongly advise against this since it runs counter to many expectations that people have when calling new:

  • People expect new to return a new object. I mean it's even called new. If you want a method that does not always create a new object, you should probably call it something else.
  • At the very least people expect Foo.new to return a Foo object. Your code will return whatever the argument is. I.e. Foo.new(42) would return 42, an Integer, not a Foo object. So if you're going to do this, you should at the very least only return the given object, if it is a Foo object.