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 callednew
. 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 aFoo
object. Your code will return whatever the argument is. I.e.Foo.new(42)
would return 42, an Integer, not aFoo
object. So if you're going to do this, you should at the very least only return the given object, if it is aFoo
object.