Why doesn't Ruby allow for overloaded methods within a class

(from a Java refugee)

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

Wes G. wrote:

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

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 L. wrote:

Wes G. wrote:

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

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

Wes G. wrote:

Thanks, I hadn’t considered that.

Wes

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 =)

Wes G. wrote:

...

Is it not available because there’s a feeling that it isn’t needed?
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

On Behalf Of Wes G.:

Here’s an example of what I mean:

class Foo

def methname(x,y)

end

def methname(x, y, z)

end

end

But it seems like this kind method overloading would be

doable in Ruby.

Is it possible?

Hi Wes,

from my nuby experience, no.

what would you expect ruby to do if you have

class A
def a
end
end

class A
def a b
end
end

?

you’d want ruby to create two methods of same name “a” but w diff
params, no? BUT, what if i really want to change method “a”, and want
it to receive 2 params among other things? "but what if i want to retain
the old “a”? ", you might ask. No problem, you can give it a different
name by alias-ing it, eg, old_a. It is easier for me to remember names
than remember different params and their combinations/positioning
thereof.

also, ruby allows this

def a *b
end

is that one or multi params?
(btw, you may not see the block param. it’s magic)

:slight_smile:

ergo, ruby does method “dynamic reloading” and loads w whatever changes
it carries w its load. it’s just a term i learn from “the matrix” :slight_smile:

Is it not available because there’s a feeling that it isn’t needed?

ruby is object oriented (not method oriented) eg, string.length,
array.length, hash.length etc. Note, no change name there (only change
in objects) and they may have diff params, too. One method name to
remember, easy for my brain.

maybe you can provide an example where you need method overloading?

kind regards -botp

It goes 100% against duck typing.

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

Wes G. wrote:

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.

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.

On 12.01.2007 09:16, Wes G. wrote:

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?

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

I’m not completely sure about this, but what would you do about optional
arguments?

Hi –

On Fri, 12 Jan 2007, Wes G. wrote:


Is it not available because there’s a feeling that it isn’t needed?
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

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.

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.