[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Modules, Overloading, and some Confusion

Old Echo

6/14/2008 10:48:00 AM

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
--
Posted via http://www.ruby-....

10 Answers

Oscar Del Ben

6/14/2008 10:57:00 AM

0

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

Use namespace.Honda::start

2008/6/14, Old Echo <kodama@bluexpanse.net>:
>
> 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
>
> --
> Posted via http://www.ruby-....
>
>

Oscar Del Ben

6/14/2008 11:00:00 AM

0

[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, Oscar Del Ben <thehcdreamer@gmail.com>:
>
> Use namespace.Honda::start
>
> 2008/6/14, Old Echo <kodama@bluexpanse.net>:
>>
>> 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
>>
>> --
>> Posted via http://www.ruby-....
>>
>>
>
>

Dave Bass

6/14/2008 11:33:00 AM

0

Old Echo 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.
--
Posted via http://www.ruby-....

Phlip

6/14/2008 12:06:00 PM

0

Old Echo wrote:

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

car = Car.new
car.start
starter = Honda.instance_method(:start)
starter.bind(car).call

I agree with other posters it should just be car.Honda::start. Maybe a gem
or another keyword should provide that flexibility.

This is important when you can't reverse the order of the includes, or
rename polymorphic methods, just to switch between two types on the fly.

You can extend the subordinate module to provide a renamer:

module Honda
def Honda_start
starter = Honda.instance_method(:start)
starter.bind(self).call
end
end

car.Honda_start

And you can trap method_missing to add _ as the :: operator:

module Honda
def method_missing(symbol)
if symbol.to_s =~ /([A-Z][\w]*)_(.*)/ and
klass = eval($1) and
starter = klass.instance_method($2.to_sym)
starter.bind(self).call
else
super
end
end
end

car.Honda_start

The major problem with this approach is we look like Visual Basic Classic.
Chills...

--
Phlip


Calamitas

6/14/2008 12:36:00 PM

0

On Sat, Jun 14, 2008 at 12:48 PM, Old Echo <kodama@bluexpanse.net> wrote:
> 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

Robert Klemme

6/14/2008 12:53:00 PM

0

On 14.06.2008 12:48, Old Echo 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

Old Echo

6/14/2008 2:09:00 PM

0

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
--
Posted via http://www.ruby-....

Phlip

6/14/2008 4:52:00 PM

0

Old Echo wrote:

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

--
Phlip
http://assert2.rubyforge.org/assert_yin...

Robert Klemme

6/14/2008 6:12:00 PM

0

On 14.06.2008 16:09, Old Echo wrote:

> 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

The Peeler

10/14/2013 10:47:00 AM

0

On Sun, 13 Oct 2013 18:10:25 -0700, The Rectum, the traumatized housebound
resident psychopath of sci and scj, FAKING his time zone again and
IMPERSONATING his master, The Peeler, wrote:

> On Sat, 24 Aug 2013 00:42:30 +0200, The Peeler
> <finishingoff@themoronicRevd.invalid> wrote:
>
24 Aug? WTF??? BWAHAHAHAHAHAHAHAHAHAHAHAHAHAHAHA!!!!!

PRICELESS!!!

--
Retarded, anal, subnormal and extremely proud of it: our resident
psychopath, The Retard (aka "The Rectum").