I've been stuck on this for quite a while now. Take a look at this:
class SuperClass
def self.new(*args, **kwargs, &block)
i = allocate()
# Extra instance setup code here
i.send(:initialize, *args, **kwargs, &block)
return i
end
end
class Test < SuperClass
def initialize
puts "No args here"
end
end
The class SuperClass
basically "reimplements" the default new
method so that some extra initialization can happen before initialize
.
Now, the following works just fine:
t = Test.allocate
t.send(:initialize, *[], **{}, &nil)
However, this does not:
t = Test.new
ArgumentError: wrong number of arguments (1 for 0) from (pry):7:in `initialize'
It fails on this line in SuperClass
:
i.send(:initialize, *args, **kwargs, &block)
But apparently it only fails if called within the new
method. I have confirmed that args == []
, kwargs == {}
and block == nil
.
Is anybody able to explain this?
Ruby version:
ruby 2.2.3p173 (2015-08-18 revision 51636) [x86_64-linux]
Please refrain from suggesting that I don't overload Class.new
. I am aware I can use Class.inherited
and Class.append
for the same result. This question is only about why the call to initialize
fails.
A simple
*args
will capture all arguments including keyword arguments, in case you don't need to referencekwargs
separately in thenew
method:Let's examine a simpler example, especially because the problem isn't as specific as the question and its title make it look like but see for yourself.
This inconsistency was introduced in 2.2.1 by a commit intended to fix a segmentation fault involving
**{}
(Bug #10719). The commit special-cases**{}
to not pass an argument. Other ways like**Hash.new
andh={};**h
still pass an empty hash as argument.Previous versions consistently raise
ArgumentError
(demo). I could be wrong but I believe that's the intended behavior. However it may or may not be the one actually wants. So if you think double-splatting an empty hash shouldn't pass an argument (like**{}
at the moment) and therefore work similar to splatting an empty array, there is an open issue about that (Bug #10856). It also mentions this relatively new inconsistency.