Modules, Overloading, and some Confusion

O

Old Echo

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
 
O

Oscar Del Ben

[Note: parts of this message were removed to make it a legal post.]

Use namespace.Honda::start
 
O

Oscar Del Ben

[Note: parts of this message were removed to make it a legal post.]

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

2008/6/14 said:
Use namespace.Honda::start
 
D

Dave Bass

Old said:
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.
 
C

Calamitas

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.

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

Or cleaner:

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

Peter
 
R

Robert Klemme

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.
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
 
O

Old Echo

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
 
P

Phlip

Old said:
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.

Absolutely. Java has both a broken specification, and huge corporate
backing. So its backers can hire a lot of writers to write that Java is
awesome, and any idiosyncrasies - such as 5,000 line config files - must be
just your fault.

Then you get Java-dependent people reciting the verbiage. Like an uneducated
redneck defending Prez Bush to the last, they are mostly trying to convince
themselves.

The basic argument against multiple inheritance is "Others have used it
wrong, therefor you are not allowed to use it, even if you could use it
right". That's obviously bogus. Others have abused 'if' statements, yet
Java allows you to freely write them, openly on the streets!
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.

In my 3 years of abusing Ruby, I first hit this problem in your post.

However, many times I have looked at the order we include things, wondering
if it could be better. One should go in order from generic to specific:

include Car
include Hybrid
include Toyota
include Prius

That won't fix your problem. Problems like yours would bite if someone
changed that order, and created a silent bug.
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.

This guy lecturing about Java - how many unit tests did he write? My
personal ratio of test to code, and the ratio on new code where I work, is
3:1.

We don't need any language features to prevent us from doing things that
_might_, in theory, break. TDD and dynamic typing allow us to work faster
than even TDD and static typing.

http://www.oreillynet.com/onlamp/blog/2008/05/dynamic_languages_vs_editors.html
 
R

Robert Klemme

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.

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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,053
Latest member
BrodieSola

Latest Threads

Top