All,
I've done quite a bit of googling and read a bunch of posts about this,
but I'm looking for a simple explanation of why Ruby doesn't support
method overloading within a class to allow methods with the same name
but different numbers of arguments. I understand that you can't do
method overloading with the same # of arguments since you don't know any
"types" of input parameters when you invoke a method.
But...it seems like you could allow it for different numbers of input
parameters.
Here's an example of what I mean:
class Foo
def methname(x,y)
...
end
def methname(x, y, z)
...
end
end
I'm comfortable with how to implement this using a method with varargs
and appropriate logic, and I'm aware of arguments that the methods
should probably be different in name if their set of input parameters
are of different size.
But it seems like this kind method overloading would be doable in Ruby.
Is it possible?
Is it not available because there's a feeling that it isn't needed?
Thanks,
Wes
--
Posted via http://www.ruby-forum.com/.
Use default arguments
def methname(x,y, z = false)
if z
else
end
If false is a valid value for z, you can try z = :special
if z == :special
Moreover, most of the time, quite a bit of code is shared from the
2-args version to the 3-args version. Actually, if that is not the case,
it is probably a sign that the functionality shouldn't be regrouped
under a unique name.
Cheers,
Vince
--
Vincent Fourmond, PhD student
http://vincent.fourmond.neuf.fr/
Theoretically, yes.
> Is it not available because there's a feeling that it isn't needed?
My guess is that Matz's reasoning here is to keep it simple.
Introducing this feature will make a lot things much more complicated -
inside the interpreter as well as for the user. Just think of method
dispatching and things like define_method and method_missing. And then
there's of course the logic: what will happen here?
class Foo
def bar(*a) end
def bar() end
end
# which method to invoke?
Foo.new.bar()
Kind regards
robert
You see, almost none of dynamic languages support this feature because
of real problems with detecting, which method to use.
class Foo
def methodname(x, y)
end
def methodname(x, *args)
end
end
Which to use in case of Foo.new.methodname(1,2) ?
Max,
Thanks, I hadn't considered that.
Wes
I've never extensively used any language that has this feature, but
it's always struck me as a bit strange, and very brittle. What if you
want two method behaviors, but both behaviors involve having the same
number of arguments? It's always seemed to me a bit like having
methods dispatch on what letter of the alphabet their parameters begin
with.
So... I guess my view is that Ruby has evolved beyond it, though there
may be some use for it that I'm just not seeing.
David
--
Q. What is THE Ruby book for Rails developers?
A. RUBY FOR RAILS by David A. Black (http://www.manning.com/black)
(See what readers are saying! http://www.rubypal.com/r4rrevs.pdf)
Q. Where can I get Ruby/Rails on-site training, consulting, coaching?
A. Ruby Power and Light, LLC (http://www.rubypal.com)
In my mind, this makes sense in a statically-typed language. The
signature of the method is reasonably clear in that case. "If I pass an
array, do A; if I pass a Vector, do B; if I pass a number, do C; if I
pass an array and a number, do D."
It seems like a very floppy, weak signature to change behavior just on
the *number* of arguments. "If I pass one thing...uhm...well, I guess
it depends on what that one thing is internally, so I'll have to branch
inside. If I pass two things...it's different from one things, but
again, it depends on which two things are passed in." You'd end up
mixing your operation determination between automatic method choosing
and between code that you have to write anyhow inside the methods.
Think about this:
class Foo
def methodname(Foo a)
puts a.value
end
def methodname(String a)
puts "bar: "+a
end
end
class FooTest < Test::Unit::TestCase
def test_methodname
@mock_foo = "some mock string value"
def @mock_foo.value
self
end
@foo = Foo.new
assert_equal "some mock string value", @foo.methodname(@mock_foo)
end
end
Problems =)
class Name < String
# ...
end
def methodName(String a)
# ...
end
Does methodName accept the Name class?
And what if you just had a NumericString class that implemented all of
the String and Numeric methods, but wasn't a descendant of either class?
Would methodName(String a) accept that class as input?
Dan
Actually, I would say that Ruby uses overloading far more than most
other languages. What does "overloading" actually mean? Basically it
means implementing more than one behaviour for the same language
element. You do that in Ruby perhaps even more than in most other
languages. In Ruby you even do it at run-time by extending classes,
replacing functions, etc.
Consider the top-level method "open". If you mixin the functionality
from the open-uri library, you are basically overloading that function
to behave differently according to the value of its arguments. Or
perhaps a better example is the 'puts' function. I don't know if it is
written in Ruby, but an implementation might look something like this:
def puts(arg)
if arg.is_a? String then
# write out the string
elsif arg.is_a? Number
s = arg.to_s
# write out the string s
else
# etc. etc.
end
end
This is basically overloading of a method. But it is implemented
entirely by the programmer with no help from the language. Now, in a
statically typed language such as Java, you cannot do the above because
the argument must specify a type. Thus, you have to do something like
void puts(String arg) {
# write out the string
}
void puts(int arg) {
# convert the int to a string and write it out
}
(Ignoring for a moment the fact that Java 1.5 introduced auto-boxing of
primitive types.)
Which is better? Which uses overloading more than the other? Neither of
them. But a language with static typing is often somewhat limited in
how much they can overload a function.
Getting back to the OP's question. What I believe he simply wants, is
some language construct that would assist him when overloading method
behaviour depending on the number of actual arguments received. That a
fair request in itself. Unfortunately, as others have pointed out, it
doesn't go too well with the fact that defining a method more than once
means overwriting the old definitions. However, I am sure some
meta-programming expert could come up with a function that would allow
us to write something like this:
overload do
def methodName(arg)
# code block A
end
def methodName(arg1, arg2)
# code block B
end
end
Basically this would be translated into something like:
def methodName1(arg)
# code block A
end
def methodName2(arg1, arg2)
# code block B
end
def methodName(arg1, arg2=nil)
if arg2.nil? then
methodName1(arg1)
else
methodName2(arg1, arg2)
end
end
I think that might be very useful in some cases actually. I wonder if
it can be done.