Modules, Overloading, and some Confusion

Hello Rubyists,
Here’s something I’ve been pondering lately and was hoping to get a good
response from someone out in the community. It’s about having two
modules which both implement a method with the same name, and then
including both modules into a class.

Example:

module Honda
def start
puts “Wroom”
end
end

module Ford
def start
puts “Rrrooom”
end
end

class Car
include Honda
include Ford
end

car = Car.new
car.start
=> Rrrroooom

Okay, so that’s a pretty contrived example, but here’s my question: how
can I can call the start method defined in Honda rather than the start
method defined in Ford? I feel like there’s something I’m missing here,
but I’m not sure what it is.

Thanks all,
kodama

Use namespace.Honda::start

2008/6/14, Old E. [email protected]:

My bad, you can’t do it the way i’ve described before.

2008/6/14, Oscar Del B. [email protected]:

Old E. wrote:

how
can I can call the start method defined in Honda rather than the start
method defined in Ford?

The point is that it’s the last-included start method that gets run.
Since Ruby is very dynamic, you can modify classes on-the-fly, even for
instantiated objects. Try this:

module Honda
def start
puts “Wroom”
end
end

module Ford
def start
puts “Rrrooom”
end
end

class Car
include Honda
end

car = Car.new
car.start # => “Wroom” … it’s a Honda

class Car
include Ford
end

car.start # => “Rrrooom” … now it’s a Ford!

However, you can’t switch back to a Honda by adding this onto the end of
the code above:

class Car
include Honda
end

car.start # => “Rrrooom” … oops, it’s still a Ford

This is because Honda has already been included once, so the new include
gets ignored (I think).

Don’t know if this solves your problem. Of course, another way around it
would be to rename one of your start methods.

On Sat, Jun 14, 2008 at 12:48 PM, Old E. [email protected]
wrote:

puts “Wroom”
class Car
can I can call the start method defined in Honda rather than the start
method defined in Ford? I feel like there’s something I’m missing here,
but I’m not sure what it is.

c = Car.new
c.start # => Rrrooom
Honda.instance_method(:start).bind(c).call # => Wroom

Or cleaner:

require ‘facets’
c.as(Honda).start # => Wroom

Peter

On 14.06.2008 12:48, Old E. wrote:

Here’s something I’ve been pondering lately and was hoping to get a good
response from someone out in the community. It’s about having two
modules which both implement a method with the same name, and then
including both modules into a class.

This is a bad idea. As others have pointed out, the last inclusion
wins. Ruby != Eiffel and Ruby != C++ - in a language like this you
better find other solutions to your problem. If you provide more
context we might come up with a solution that is better suited to Ruby.

Example:

Okay, so that’s a pretty contrived example,

Yes, it is. Your car can only be one make at a time, i.e. there is no
point in including both modules at the same time.

but here’s my question: how
can I can call the start method defined in Honda rather than the start
method defined in Ford? I feel like there’s something I’m missing here,
but I’m not sure what it is.

For the fun of it: you can find an incomplete solution at the end.

Kind regards

robert

#!/bin/env ruby

class Module
class Proxy
def initialize(mod, obj)
@mod = mod
@obj = obj
end

 def method_missing(m,*a,&b)
   @mod.instance_method(m).bind(@obj).call(*a,&b)
 end

 # other methods must be undefined

end

def scope(obj)
Proxy.new self, obj
end
end

module Honda
def start
puts “Wroom”
end
end

module Ford
def start
puts “Rrrooom”
end
end

class Car
include Honda
include Ford
end

car = Car.new
car.start
Ford.scope(car).start
Honda.scope(car).start

Hello all,
Thank you for your responses. This is more of a philosophical rather
than a practical question – I’m not facing this situation in any
application that I’m trying to write.

Background: I used to work at a company that was an all-Java shop where
I would occasionally debate the merits of Ruby vs. Java (dynamic vs.
static, etc etc etc) with one of my co-workers who is a big Java guy.
Somehow the topic of multiple inheritance came up, and one of the “shoot
Ruby down” arguments was that because of this “last-one-in” wins
behavior, Ruby couldn’t really help solve the issues that come up when
trying to do multiple inheritance. Of course, it was pointed out that
Java doesn’t really have a good way to do this either, but I left the
conversation feeling like something was amiss with the argument.

Now, I’ve wracked my brain for a real example of when you’d actually
run into this kind of problem where two modules define the same method,
and then when you mix both in to a class, problems come up. I can’t
really think of any - which leads me to believe that the problem set for
these things is different in Ruby than in language where the type system
is more strict.

But again, these are really just philosophical ponderings more than
anything else. Good discussion, though! I’d love to hear more from
anyone who has thoughts on this.

Thanks,
kodama

On 14.06.2008 16:09, Old E. wrote:

trying to do multiple inheritance. Of course, it was pointed out that
Java doesn’t really have a good way to do this either, but I left the
conversation feeling like something was amiss with the argument.

Well, first of all: as has been demonstrated, there are in fact ways
to deal with this situation in Ruby. But: IMHO it is not a too good
design to inherit from two classes that share a common part in their
signatures (public interface). Granted, there are some methods with
obvious names (like “size”, “length”) that are likely to be present in
multiple classes and you cannot completely prevent this situation. But
resolving this is ugly - no matter what programming language you use.
Even in Eiffel - where you have sophisticated means to resolve such
situations and the language is very strict about not allowing
ambiguities - I would find a situation ugly where two classes that share
common methods would be publicly inherited (i.e. “is a” relationship is
visible to clients of the class).

But again, these are really just philosophical ponderings more than
anything else. Good discussion, though! I’d love to hear more from
anyone who has thoughts on this.

Yes, it’s good to think about these topics from time to time! And it
reminds me that I have to reread Bertrand Meyer’s book OOSE again.

Kind regards

robert