Method overloading like Java?

In Java, you could write the following code:
public void foo(int x)
{ /* do something*/ }

public void foo(String x)
{ /* do something*/ }

int x1
String x2

foo(x1)
foo(x2)

The 2nd to last line would call the first foo and the last line would call the 2nd foo.

Is there a way to do this in Ruby? I am aware of method(*args) and case...when but I think Java's version is cleaner and more readable. I also know that variables in Ruby are dynamically typed, the method that is called should be based on the most recent type of the variable being passed.

I don't want to do this:
def foo(arg)
if arg.type_of? String
  # do something
elsif arg.type_of? Numeric
  #do something
else
  raise args error
end

thanks,
Dan

Hi --

In Java, you could write the following code:
public void foo(int x)
{ /* do something*/ }

public void foo(String x)
{ /* do something*/ }

int x1
String x2

foo(x1)
foo(x2)

The 2nd to last line would call the first foo and the last line would call the 2nd foo.

Is there a way to do this in Ruby? I am aware of method(*args) and case...when but I think Java's version is cleaner and more readable. I also know that variables in Ruby are dynamically typed, the method that is called should be based on the most recent type of the variable being passed.

I don't want to do this:
def foo(arg)
if arg.type_of? String
  # do something
elsif arg.type_of? Numeric
  #do something
else
  raise args error
end

It's not just a matter of dynamic vs. static typing. In Ruby, an
object's class (i.e., what it's an instance of, what it reports when
you call #class on it) is not necessarily representative of the type
of the object (i.e., the capabilities of the object, the methods it
knows, at any given point in its life).

Over the years there have been various mechanisms proposed (and in
some cases written as add-on libraries) that check the class or
class/module ancestry of objects, and either dispatch differentially
based on those criteria or raise errors if the criteria aren't met.
These systems all suffer from two major problems:

   1. they don't work, because they don't account for the possibility
      of an object's having behavior that doesn't derive from its class
      of origin;
   2. by setting up a kind of phantom "type"-checking (i.e., class-
      checking, in a language where type != class), they tend to
      discourage thinking about other ways in which Ruby objects can
      be engineered, and some of the freedoms available to those
      objects.

There have also been some interesting attempts to define and profile
the type of Ruby objects. It's difficult: it involves consideration
of, at least, the methods the object responds to (which can change),
how those methods behave, and any publicly changeable state in the
object. I don't think any of these attempts has been completed (and
they've been attempted by some very good programmers). Ultimately,
"type" in Ruby is a circularity: an object's type is "the type which
objects that are just like this object have", or something like that.
Type is elusive, but that rarely matters.

David

···

On Mon, 4 Dec 2006, Daniel Finnie wrote:

--
                   David A. Black | dblack@wobblini.net
Author of "Ruby for Rails" [1] | Ruby/Rails training & consultancy [3]
DABlog (DAB's Weblog) [2] | Co-director, Ruby Central, Inc. [4]
[1] Ruby for Rails | [3] http://www.rubypowerandlight.com
[2] http://dablog.rubypal.com | [4] http://www.rubycentral.org

Daniel Finnie wrote:

In Java, you could write the following code:
public void foo(int x)
{ /* do something*/ }

public void foo(String x)
{ /* do something*/ }

int x1
String x2

foo(x1)
foo(x2)

The 2nd to last line would call the first foo and the last line would call the 2nd foo.

Is there a way to do this in Ruby? I am aware of method(*args) and case...when but I think Java's version is cleaner and more readable. I also know that variables in Ruby are dynamically typed, the method that is called should be based on the most recent type of the variable being passed.

I don't want to do this:
def foo(arg)
if arg.type_of? String
    # do something
elsif arg.type_of? Numeric
    #do something
else
    raise args error
end

thanks,
Dan

Java's (and C++'s) kind of method overloading just isn't do-able in Ruby. Generally, if you have a method that can take either a String or a Numeric argument, then you create two methods, one that takes a String argument and another for the Numeric argument.

Switching on the class of an argument is also regarded with suspicion but is acceptable in some cases. Search for "duck typing" in the Pickaxe or in the archives of this mailing list for exhaustive discussions.

Daniel Finnie wrote:

I don't want to do this:
def foo(arg)
if arg.type_of? String
    # do something
elsif arg.type_of? Numeric
    #do something
else
    raise args error
end

1. That's the only way to do it.

2. You'd be better served if you considered code like that a smell. If you've got a method whose functionality varies _vastly_ based on the type of its arguments, then they probably deserve to be separate methods, with more descriptive names.

Devin

Is there a way to do this in Ruby? I am aware of method(*args) and
case...when but I think Java's version is cleaner and more readable. I
also know that variables in Ruby are dynamically typed, the method that
is called should be based on the most recent type of the variable being
passed.

What about this?

class String
  def foo
    puts 'String'
  end
end

class Numeric
  def foo
    puts 'Numeric'
  end
end

x1 = 1
x2 = 'string'

x1.foo
x2.foo

You can emulate it - although I am not convinced that it is a good idea.

http://wiki.rubygarden.org/Ruby/page/show/MethodOverloading
http://wiki.rubygarden.org/Ruby/page/show/RubyFromCpp

Kind regards

  robert

···

On 04.12.2006 03:37, Daniel Finnie wrote:

In Java, you could write the following code:
public void foo(int x)
{ /* do something*/ }

public void foo(String x)
{ /* do something*/ }

EXACTLY

If you want different types of objects to perform different behavior
for the same method call, you use polymorphism. What OP wants to do
is essentially a design pattern for providing polymorphism
capabilities to a language that doesn't have them built in.

Pat

···

On 12/3/06, Gordon Thiesfeld <gthiesfeld@gmail.com> wrote:

> Is there a way to do this in Ruby? I am aware of method(*args) and
> case...when but I think Java's version is cleaner and more readable. I
> also know that variables in Ruby are dynamically typed, the method that
> is called should be based on the most recent type of the variable being
> passed.

What about this?

class String
  def foo
    puts 'String'
  end
end

class Numeric
  def foo
    puts 'Numeric'
  end
end

x1 = 1
x2 = 'string'

x1.foo
x2.foo

But how about overloading by parameter numbers. such as:
class FooClass {
   def foo(first){ }
   def foo(first, second) { }
}

does ruby support this ? if can not, how can we workaround this?

thanks

···

2006/12/4, Pat Maddox <pergesu@gmail.com>:

On 12/3/06, Gordon Thiesfeld <gthiesfeld@gmail.com> wrote:
> > Is there a way to do this in Ruby? I am aware of method(*args) and
> > case...when but I think Java's version is cleaner and more
readable. I
> > also know that variables in Ruby are dynamically typed, the method
that
> > is called should be based on the most recent type of the variable
being
> > passed.
>
> What about this?
>
> class String
> def foo
> puts 'String'
> end
> end
>
> class Numeric
> def foo
> puts 'Numeric'
> end
> end
>
> x1 = 1
> x2 = 'string'
>
> x1.foo
> x2.foo

EXACTLY

If you want different types of objects to perform different behavior
for the same method call, you use polymorphism. What OP wants to do
is essentially a design pattern for providing polymorphism
capabilities to a language that doesn't have them built in.

Pat

class Foo
    def foo(first, second = nil)
    end
  end

-austin

···

On 12/3/06, Yang Bob <bob.yang.dev@gmail.com> wrote:

But how about overloading by parameter numbers. such as:
class FooClass {
   def foo(first){ }
   def foo(first, second) { }
}

does ruby support this ? if can not, how can we workaround this?

--
Austin Ziegler * halostatue@gmail.com * http://www.halostatue.ca/
               * austin@halostatue.ca * You are in a maze of twisty little passages, all alike. // halo • statue
               * austin@zieglers.ca

There's also this one:

def foo opts={}
  if opts[:some_parameter]
    do_something_with_parameter
  end

  if opts[:some_other_parameter]
    do_something_with_other_parameter
  end
end

foo :some_parameter=>123, :some_other_parameter=>'abc'

This is used as a substitute for 'true' named parameters. It is mostly
useful if you need to take a moderate number of entirely optional
parameters.

Cheers,
Max

···

On 12/4/06, Yang Bob <bob.yang.dev@gmail.com> wrote:

But how about overloading by parameter numbers. such as:
class FooClass {
   def foo(first){ }
   def foo(first, second) { }
}

does ruby support this ? if can not, how can we workaround this?

thanks

it's good and simple. thanks

···

2006/12/4, Austin Ziegler <halostatue@gmail.com>:

On 12/3/06, Yang Bob <bob.yang.dev@gmail.com> wrote:
> But how about overloading by parameter numbers. such as:
> class FooClass {
> def foo(first){ }
> def foo(first, second) { }
> }
>
> does ruby support this ? if can not, how can we workaround this?

  class Foo
    def foo(first, second = nil)
    end
  end

-austin
--
Austin Ziegler * halostatue@gmail.com * http://www.halostatue.ca/
               * austin@halostatue.ca * You are in a maze of twisty little passages, all alike. // halo • statue
               * austin@zieglers.ca

I prefer this method if I have many parameters, and when I have just fewer
parameters I prefer Austin Ziegler's method.

Thanks : )

···

2006/12/4, Max Muermann <ruby@muermann.org>:

On 12/4/06, Yang Bob <bob.yang.dev@gmail.com> wrote:
> But how about overloading by parameter numbers. such as:
> class FooClass {
> def foo(first){ }
> def foo(first, second) { }
> }
>
> does ruby support this ? if can not, how can we workaround this?
>
> thanks
>

There's also this one:

def foo opts={}
  if opts[:some_parameter]
    do_something_with_parameter
  end

  if opts[:some_other_parameter]
    do_something_with_other_parameter
  end
end

foo :some_parameter=>123, :some_other_parameter=>'abc'

This is used as a substitute for 'true' named parameters. It is mostly
useful if you need to take a moderate number of entirely optional
parameters.

Cheers,
Max