Forum: Ruby inheritance concept in ruby

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
C08665e38dc6b3936591c4b83c329749?d=identicon&s=25 Kumar Tnj (tnjnew)
on 2007-01-09 12:33
Hi,

Is ruby supports multiple inheritence.
I am the beginner of ruby.
simple code for ruby multiple inheritence.

Thanks & Regards,
Kumar
87e41d0d468ad56a3b07d9a6482fd6d5?d=identicon&s=25 Hemant Kumar (gnufied)
on 2007-01-09 12:43
(Received via mailing list)
On 1/9/07, Kumar Tnj <senvenit2003@india.com> wrote:
> Hi,
>
> Is ruby supports multiple inheritence.
> I am the beginner of ruby.
> simple code for ruby multiple inheritence.
>
> Thanks & Regards,
> Kumar
>

multiple inheritence is not supported in Ruby. However via modules and
mixins ruby achieves almost the same functionality.
25e11a00a89683f7e01e425a1a6e305c?d=identicon&s=25 Wilson Bilkovich (Guest)
on 2007-01-09 18:23
(Received via mailing list)
On 1/9/07, Kumar Tnj <senvenit2003@india.com> wrote:
> Hi,
>
> Is ruby supports multiple inheritence.
> I am the beginner of ruby.
> simple code for ruby multiple inheritence.
>

To expand on what hemant said.. try running this code.

class Useless
  def six
    6
  end
end

module AlsoUseless
  def seven
    7
  end
end

class Thing < Useless
  include AlsoUseless
  def five
    5
  end
end

thing = Thing.new
puts thing.five
puts thing.six
puts thing.seven
puts Thing.ancestors.inspect # Useless and AlsoUseless are shown.
F819599bbed80f48013d5acad012a9c3?d=identicon&s=25 Helder Ribeiro (Guest)
on 2007-01-19 16:30
(Received via mailing list)
Wilson Bilkovich wrote:
> class Useless
>
> puts thing.seven
> puts Thing.ancestors.inspect # Useless and AlsoUseless are shown.

I'm also new to Ruby and I've never used anything with multiple
inheritance. This code is enlightening but I can't see how this is
different from multiple inheritance in practice except that AlsoUseless
is not a class and you don't use the '<' sign with it.

In which cases do the two scenarious (M.I. and mixins) cause different
behaviors? Is it only related to member visibility? If yes, how
exactly?

Thanks!

Helder
25e11a00a89683f7e01e425a1a6e305c?d=identicon&s=25 Wilson Bilkovich (Guest)
on 2007-01-19 16:31
(Received via mailing list)
On 1/11/07, Helder Ribeiro <helder@gmail.com> wrote:
> > To expand on what hemant said.. try running this code.
> >   end
> > puts thing.five
> behaviors? Is it only related to member visibility? If yes, how
> exactly?
>

Multiple Inheritance can be extremely complex, as Gregory Brown has
pointed out.
One complication is that you now have to have rules to 'break ties'
when you write:
def hello
  super
end

What if each of the parent classes has their own implementation of
'hello'. Which one is invoked? Mix-ins simplify this greatly, because
there is still only one unambiguous superclass.

If you have used Java, they are like having Interfaces containing
working code, as well as just a list of what should be implemented.
F819599bbed80f48013d5acad012a9c3?d=identicon&s=25 Helder Ribeiro (Guest)
on 2007-01-19 16:31
(Received via mailing list)
Wilson Bilkovich wrote:
> 'hello'. Which one is invoked? Mix-ins simplify this greatly, because
> there is still only one unambiguous superclass.

Ok, I see this is a problem with multiple-inheritance, but it doesn't
seem to me like one that using Modules solves. When checking another
discussion*, I went to the PickAxe to check method lookup with modules
and got this:

"The answer is that Ruby looks first in the immediate class of an
object, then in the
mixins included into that class, and then in superclasses and their
mixins. *If a class has
multiple modules mixed in, the last one included is searched first*."

That is, the exact same thing happens when you have a class include two
modules and both implement the 'hello' method. There is no self-evident
way of choosing, so you have to come up with an arbitrary choice like
that of order of call to 'include'.

>
> If you have used Java, they are like having Interfaces containing
> working code, as well as just a list of what should be implemented.

This is interesting. Does Ruby allow codeless methods in a module like
those of an java interface?

* The discussion I refer to is at
http://groups.google.com/group/comp.lang.ruby/brow...

I'm not done reading it yet but has been very enlightening so far. I
cite it so Kumar can take a look at it as I think it's related to this.
The next question that comes after the answer to "does it have multiple
inheritance" is "what's with those modules?!". I'll try and look up
more stuff so I don't repeat questions here. Thanks so far to those who
answered =)

Helder
31e038e4e9330f6c75ccfd1fca8010ee?d=identicon&s=25 Gregory Brown (Guest)
on 2007-01-19 16:32
(Received via mailing list)
On 1/12/07, Helder Ribeiro <helder@gmail.com> wrote:

> That is, the exact same thing happens when you have a class include two
> modules and both implement the 'hello' method. There is no self-evident
> way of choosing, so you have to come up with an arbitrary choice like
> that of order of call to 'include'.

To me, it's the most intuitive choice as it reflects intrepretation
order

class Child < Parent #imbue with ancestry

  include Foo # imbue with foo's definitions
  include Bar # imbue with bar's definitions

  def something  # imbue with actual definition

  end

 end

All that is happening is Ruby's applying the changes as it sees them.

So the path there is super clear

Child -> Bar -> Foo -> Parent.

Maybe this is surprising to those working in non-interpreted languages
though.  I'm not sure.
31e038e4e9330f6c75ccfd1fca8010ee?d=identicon&s=25 Gregory Brown (Guest)
on 2007-09-25 22:30
(Received via mailing list)
On 1/11/07, Helder Ribeiro <helder@gmail.com> wrote:

> I'm also new to Ruby and I've never used anything with multiple
> inheritance. This code is enlightening but I can't see how this is
> different from multiple inheritance in practice except that AlsoUseless
> is not a class and you don't use the '<' sign with it.

The real complication with multiple inheritance is that you end up
inheriting the ancestors of both parent classes.

When you use a mixin, the additional methods are tacked on to a class
in the heirarchy, rather than creating another set of ancestors.

Since modules live outside of the tree of inheritance, they can be
used to provide functionality without complicating the ancestry chain.

See Comparable and Enumerable for excellent and practical uses of
modules.

> In which cases do the two scenarious (M.I. and mixins) cause different
> behaviors? Is it only related to member visibility? If yes, how
> exactly?

if:

A < B < C

and module D is mixed into C, there is still a single path back to A.

Had we used multiple inheritence (if it were possible), perhaps

F < E < D

so now, C has two distinct roots, A and F.

Now imagine circular dependencies and other complications.  Scary! :)

So modules allow you to avoid the verbosity of interfaces without
complicating the chain of ancestors.
F819599bbed80f48013d5acad012a9c3?d=identicon&s=25 Helder Ribeiro (helder)
on 2007-09-25 22:32
(Received via mailing list)
dblack@wobblini.net wrote:

> I don't think anyone came up with a strictly technical, bullet-proof
> objection to class/module unification when Mathieu was advocating it.
> Basically, if all the modules in the lookup-path were, instead,
> classes, I don't think anything we can do now would be impossible
> (assuming the lookup rules were preserved).  In that sense the
> presence of the difference is more a matter of semantic enrichment
> than technical extension.

Perfect! That was exactly what I was beginning to think. You summed it
up very well :-)

Thanks a lot, David!

Cheers,

Helder
31e038e4e9330f6c75ccfd1fca8010ee?d=identicon&s=25 Gregory Brown (Guest)
on 2007-09-25 22:34
(Received via mailing list)
On Jan 12, 3:45 pm, "Per Velschow" <Per.Velsc...@gmail.com> wrote:
> > This is interesting. Does Ruby allow codeless methods in a module like
> > those of an java interface?That wouldn't make sense. The only reason for having 
methods defined
> with no code is when you have static type checking as in Java. In Ruby
> everything happens at run-time.

However, this is much more powerful, because it allows you to reference
methods in your modules that you
expect classes to implement.

For example,  all you need is <=> to get all of Comparable, and #each
to get Enumerable.

Designing with this in mind can be *very* powerful
E7559e558ececa67c40f452483b9ac8c?d=identicon&s=25 unknown (Guest)
on 2007-09-25 22:39
(Received via mailing list)
On Jan 23, 2007, at 10:35 AM, Helder Ribeiro wrote:

> Perfect! That was exactly what I was beginning to think. You summed it
> up very well :-)


I've been meaning to followup on this discussion.

I also chewed on the idea that modules and classes were a needless
division for quite a while but I've come to appreciate the differences
if not from a theoretical sense certainly from a practical sense.

In any case, one thing that I think is distinctly different between
modules and classes is that classes are placed inside a tree structure
when they are *defined* but that the relationship between modules is
much more dynamic as it depends on the execution of the 'include'
method.

So classes always spring into existence as a leaf on the inheritance
tree while modules are independent objects until they are explicitly
included into another module, which may never happen at all.

I haven't sorted out in my mind all the implications but it feels
like this introduces an important semantic difference.

Also the semantics of 'include' create something that is more
constrained than an arbitrary DAG (directed acyclical graph).  At
least I think so.   MI would permit the creation of completely
general DAGs.  So this also leads me to believe that there are
theoretical as well as practical differences between MI and mixin
strategies.


Gary Wright
F819599bbed80f48013d5acad012a9c3?d=identicon&s=25 Helder Ribeiro (helder)
on 2007-09-25 22:41
(Received via mailing list)
Gregory Brown wrote:
> On 1/16/07, Helder Ribeiro <helder@gmail.com> wrote:

> > Yes, i meant any method call. But I haven't found this lookup order
> > stated in its full anywhere else. The part after the "*and*" is what I
> > inferred from what the PickAxe says about the other cases (the quote is
> > in this thread somewhere).
>
> Perhaps we need to document this better.  I'm not sure where the best
> place would be, though.

Yes, definetely. The only thing I managed to dig on this was this
thread from way back that I don't even know if still fits (and haven't
read in full to know if it the guy ended up getting a well-defined
method resolution order).
http://groups.google.com/group/comp.lang.ruby/brow...

> > "since Ruby already has a well-defined lookup order that takes care of
> > conflicts in class/module hierarchies, couldn't you have a similarly
> > well-defined lookup order for Multiple Inheritance and do away with
> > Modules altogether?"
>
> Probably.  But the question is, why would you want to do this?  I
> suppose what would be important to know is whether this interest in
> the system is of theoretical or practical grounds for you.

It is of theoretical grounds. The question I posed with "do away with
modules" is actually a way to understand some theoretical difference
that there must exist between MI and Modules, not that I actually think
Modules should be done away with. It is a sort of proof by absurd. The
discussion so far has been sort of like:

"modules are needed to avoid a set X of problems with MI";
"but modules have those same problems in X";
"but in modules you solve problems in X with Y";
"but in MI you can solve those same problems in X with Y"

So the first sentence is false, at least for the problems in X (name
conflicts in multiple parent hierarchies). You can solve them both in
MI and Modules with Y (a well-defined resolution order).

Unless, of course, there is some fundamental difference that makes
possible the existence of a well-defined resolution order (Y) for
Modules but not for MI. That's what I'm trying to find out, and it
there *must* be some such difference, otherwise why would people have
come up with Modules in the first place? Only because, although having
the same problems, it inspires a different mindset in programmers so
that they are less prone to running into those problems?

> If it is
> of theoretical grounds, these are all valid questions, but I do think
> they'd end up somewhere around the 'this is how matz implemented them,
> so unless something Really Wrong with them can be shown, they're here
> to stay' conclusion.

Yeah, I'm not saying it's wrong and should be changed. I'm saying there
must be a reason for it and I'm trying to understand Ruby better by
understanding that.
>
> Tie breaking rules are necessary when you end up with cycles in the graph.
> The MRO for Python 2.3 is pretty straightforward, mostly because it
> fails if this occurs (preventing the need for complex tie breaking
> rules).
>
> http://www.python.org/download/releases/2.3/mro/

Very good reference! Helped a lot!

> With mixins however, there is no situation where this would occur,
> which is one of it's strengths.

But cycles can't exist in either. I think the problems the reference
addresses are more subtle (I've read about monotonicity so far but
there's also one about "local precedence ordering") and, while the
*class* hierarchy doesn't have them (single inheritance), I'm not sure
if a hierarchy of modules alone can't show them.

> perhaps a class would be appropriate.
>
> Sometimes this changes as you go through your development process.
> Sometimes you realize you only needed a module and you used a class.
> Or sometimes the opposite happens.  So it's not like Ruby is forcing
> your hand to do one or the other.  The relative similarities between
> the two make it somewhat easy to refactor from one to another without
> changing much.

Very nice. I think it's mostly a style thing than, as you said. The
Classes/Moudles thing is probably a good mind frame to think in.

And the theoretical differences must be so subtle that in the end it
probably wouldn't influence much when you're programming anyway.

Besides that, I've nagged for long enough already, and it's kinda
fallen out of the scope of a list discussion. If I'm really serious
about the details I'd probably have to go through some books on
compilers, grammars and stuff.

It'd be good to have some greater understanding of the Ruby MRO though,
leaving aside the Modules/MI quest-for-difference a little.

Perhaps I'll dig it up a bit more and write something on it to share
with people. Anyone interested in helping out (in the digging and/or in
the writing)?? =)

Anyway, thanks a lot Greg and everyone. It's been a great first
incursion into ruby-talk and I'm positively impressed =)

Cheers,

Helder
F819599bbed80f48013d5acad012a9c3?d=identicon&s=25 Helder Ribeiro (helder)
on 2007-09-25 22:41
(Received via mailing list)
Gregory Brown wrote:
> which logically is quick intuitive if you think about it.
> that you cannot be sure what they implement without knowing the
> ancestors of each.

That's true. It made me think of one thing though. The PickAxe, at
least in that part I quoted, is silent about lookup order when mixed-in
modules include modules. If you extend the reasoning, though, you can
say that when a method call is made inside a class method, Ruby first
checks for methods in that class, then in the modules it includes (so
far nothing new) *and*, inside those modules, first for methods they
implement themselves, and then for methods defined in modules mixed
into them.

So how would this be different from the scenario you suggested with
multiple inheritance? You can get an exactly analog problem, where the
conflict might lie not in immediate dependencies, but in dependency
chains. A->B->C can be the class hierarchy while ?->D->C and ?->E->C
are module hierarchies.

I didn't understand what you meant by "you cannot be sure what they
implement without knowing the ancestors of each". Isn't that true even
for A->B->C alone? You can't know what C implements unless you know B
and C.

And if the problem is only lookup order, separating class hierarchy
from module hierarchy makes it easier only in the case where you have
*one* class hierarchy (A->B->C) and *one* module hierarchy (F->D->C),
because it is given that you choose first from the class hierarchy. For
cases of 3+ you still have the same problems, right?

And yet, this is a problem only when there is name collision which, as
you said, is a small case and mostly due to code smell or unavoidable
complexity.

What I don't see is what exactly having separate class/module
hierarchies buys you. You ensure a simple tree structure for the class
inheritance graph, but you (apparently) don't have that for the module
graph and they are both connected. Doesn't that blow the idea of tree
for the former?

The only thing holding me from saying "it's a tree, *connected* to a
general network, thus it's all a big network" is that the connection
seems to be unidirectional (modules can't have classes 'mixed in' or
inherit from them, I suppose). Is there some theoretical result that
bases itself on this (or some other thing, I dunno) to say that there
is a clear distinction between the M.I. model and the "tree +
pan-inheritance-modules"?

Furthermore, if both models are almost (or perhaps completely)
equivalent *and* the only problem is with the limited case of name
collision and that can be solved with lookup rules, where is the source
of contention? Why would people favor one over the other?

Sorry for the verbosity and thanks for the nice conversation.

Cheers,

Helder
31e038e4e9330f6c75ccfd1fca8010ee?d=identicon&s=25 Gregory Brown (Guest)
on 2007-09-25 22:41
(Received via mailing list)
Hi Helder, sorry it took me a while to get back to these questions,
but I've done what I could to answer them below.

I can't remember where in the thread you talked about a class
hierarchy vs. a mixin hierarchy.

The thing is, though it is likely you'll end up on a long chain of
subclasses in a complex system, it's unlikely you'll run into a deeply
nested set of modules.  Even when you do, these modules will typically
implement things that are orthogonal from each other, so you can still
look at any given module as a distinct unit living outside of the
class heirarchy.

Once mixed in, it more or less becomes part of the class definition,
and the call order is pretty intuitive in practice.  The same cannot
be said for Multiple Inheritance unless the system is designed with
much care.  That's the core of the reasoning behind modules as far I
can tell, and the responses that follow have that in mind...

On 1/16/07, Helder Ribeiro <helder@gmail.com> wrote:

> > I'm not sure you really mean class method here.  What you're saying is
> > true of any time you send a message to an object -- that is, it looks
> > in its class, then the modules, etc.
>
> Yes, i meant any method call. But I haven't found this lookup order
> stated in its full anywhere else. The part after the "*and*" is what I
> inferred from what the PickAxe says about the other cases (the quote is
> in this thread somewhere).

Perhaps we need to document this better.  I'm not sure where the best
place would be, though.

> But this is an artificial difference, because you can define a lookup
> order to solve this conflict without the need for Modules. So the
> question is
>
> "since Ruby already has a well-defined lookup order that takes care of
> conflicts in class/module hierarchies, couldn't you have a similarly
> well-defined lookup order for Multiple Inheritance and do away with
> Modules altogether?"

Probably.  But the question is, why would you want to do this?  I
suppose what would be important to know is whether this interest in
the system is of theoretical or practical grounds for you.  If it is
of theoretical grounds, these are all valid questions, but I do think
they'd end up somewhere around the 'this is how matz implemented them,
so unless something Really Wrong with them can be shown, they're here
to stay' conclusion.  It is good to talk about these things because it
lets us understand better how they work, but I'm not sure that I've
seen many cases *for* MI in ruby.  Since we seem to be getting along
fine without them, the whole "If it ain't broke, don't fix it" adage
applies.

If your interest in this is based on a practical modeling issue, I
think it'd be better for you to describe the model that you are
dealing with so we can help you think of ways to express it cleanly in
Ruby.  Perhaps seeing the way modules are used in practice would help
clear some of the fuzzy areas up for you.

> > There's still the possibility of name collision with mixins, but there
> > are (to my knowledge) no special cases, no need for tie-breaking rules
> > -- because the rules that are there in the first place make a tie
> > impossible.
>
> Don't understand what you're saying. There is, indeed, no need for
> tie-breaking rules if you have lookup order rules (i'm assuming those
> are what you mean by "the rules that are there"). It happens that they
> are the same, though, you're just giving them different names.

Tie breaking rules are necessary when you end up with cycles in the
graph.
The MRO for Python 2.3 is pretty straightforward, mostly because it
fails if this occurs (preventing the need for complex tie breaking
rules).

http://www.python.org/download/releases/2.3/mro/

With mixins however, there is no situation where this would occur,
which is one of it's strengths.

> >
> > > The only thing holding me from saying "it's a tree, *connected* to a
> > > general network, thus it's all a big network" is that the connection
> > > seems to be unidirectional (modules can't have classes 'mixed in' or
> > > inherit from them, I suppose). Is there some theoretical result that
> > > bases itself on this (or some other thing, I dunno) to say that there
> > > is a clear distinction between the M.I. model and the "tree +
> > > pan-inheritance-modules"?

Actually, multiple inheritence is meant more-or-less to solve the same
problem, to unify orthogonal concerns.  To me it's just a cleaner
system to accomplish the same basic goal, while providing a little bit
more protection against shooting yourself in the foot.

However, the same problems can indeed arise from both, I just think
the mixin model puts you in a  mindframe that discourages that. (One
you get used to how it works)

> > > Furthermore, if both models are almost (or perhaps completely)
> > > equivalent *and* the only problem is with the limited case of name
> > > collision and that can be solved with lookup rules, where is the source
> > > of contention? Why would people favor one over the other?

> unsuitable for what you do (I know nothing about domain modeling)?
This is mostly a style thing.

If you think of some module names, you get things like Comparable and
Enumerable.

Now let's put that in the context of use with classes.

Some object is an Array.  That Array is Enumerable.
Some object is a Fixnum. That Fixnum is Comparable.

So just like using any concept to organize your code, on it's own,
there is little technical difference.
But it is very powerful when you use the concepts right.  You say,
hmm... I'm looking at a relationship in which this chunk of code
describes the kinds of things you can do with an object if it meets
certain criteria, that sounds like a module would make sense.  Or,
this object embodies something rather concrete with unique behaviors,
perhaps a class would be appropriate.

Sometimes this changes as you go through your development process.
Sometimes you realize you only needed a module and you used a class.
Or sometimes the opposite happens.  So it's not like Ruby is forcing
your hand to do one or the other.  The relative similarities between
the two make it somewhat easy to refactor from one to another without
changing much.
1fba4539b6cafe2e60a2916fa184fc2f?d=identicon&s=25 unknown (Guest)
on 2007-09-25 22:43
(Received via mailing list)
Hi --

On Mon, 15 Jan 2007, Helder Ribeiro wrote:

>>
>> Those two question marks represent two independent dependency chains
> into them.
I'm not sure you really mean class method here.  What you're saying is
true of any time you send a message to an object -- that is, it looks
in its class, then the modules, etc.

>
> And if the problem is only lookup order, separating class hierarchy
> from module hierarchy makes it easier only in the case where you have
> *one* class hierarchy (A->B->C) and *one* module hierarchy (F->D->C),
> because it is given that you choose first from the class hierarchy. For
> cases of 3+ you still have the same problems, right?

No, the lookup order principle still keeps it uniform.  It's useful to
think of it from the object's point of view.  You send a message to an
object, and it goes on a search for a method with a corresponding
name.  This search always takes place along an unambiguous, one-track
path.  The object doesn't see trees or forks in the road.

It's all based on order of inclusion, but I don't think that's an
arbitrary choice.  It's very much in keeping with the dynamic nature
of Ruby objects.  In fact, it *is* the dynamic nature of Ruby
objects; the singleton classes that allow for per-object behavior are
part of this system too.

There's still the possibility of name collision with mixins, but there
are (to my knowledge) no special cases, no need for tie-breaking rules
-- because the rules that are there in the first place make a tie
impossible.  Dealing with things like name collision is reduced
entirely to a function of knowing what's in the source code.  You need
to know whether a module you're including is going to occlude a method
further up the chain; but the rules that determine this are the same
as the rules that are in operation all along.

> And yet, this is a problem only when there is name collision which, as
> you said, is a small case and mostly due to code smell or unavoidable
> complexity.
>
> What I don't see is what exactly having separate class/module
> hierarchies buys you. You ensure a simple tree structure for the class
> inheritance graph, but you (apparently) don't have that for the module
> graph and they are both connected. Doesn't that blow the idea of tree
> for the former?

Maybe, but in the end it's not really a tree model; it's a path model.
When you include modules in classes, you're inserting them in the
method look-up path of instances of those classes.

> collision and that can be solved with lookup rules, where is the source
> of contention? Why would people favor one over the other?

The thing I like about modules is that I find the model a suggestive
way of thinking about domain modeling.  I like having both a noun-like
thing (classes) and an adjective-like thing (modules).  Then again,
all of this is purely in the context of Ruby; I don't inherently like
one or the other more.


David
1fba4539b6cafe2e60a2916fa184fc2f?d=identicon&s=25 unknown (Guest)
on 2007-09-25 22:46
(Received via mailing list)
Hi --

On Wed, 17 Jan 2007, Helder Ribeiro wrote:

> and B being classes - since they have equal rank in the hierarchy -
> doesn't exist when B is a module, because modules have lower priority.
>
> But this is an artificial difference, because you can define a lookup
> order to solve this conflict without the need for Modules. So the
> question is
>
> "since Ruby already has a well-defined lookup order that takes care of
> conflicts in class/module hierarchies, couldn't you have a similarly
> well-defined lookup order for Multiple Inheritance and do away with
> Modules altogether?"

Yes, almost certainly.  There was a big push for class/module by
Mathieu Bouchard, a couple of years ago.  The discussion was mostly on
ruby-core, and would be in the archives.

>> There's still the possibility of name collision with mixins, but there
>> are (to my knowledge) no special cases, no need for tie-breaking rules
>> -- because the rules that are there in the first place make a tie
>> impossible.
>
> Don't understand what you're saying. There is, indeed, no need for
> tie-breaking rules if you have lookup order rules (i'm assuming those
> are what you mean by "the rules that are there"). It happens that they
> are the same, though, you're just giving them different names.

I'm probably not expressing the tree (or lack thereof) thing and the
rules thing very clearly.  I guess what I'm saying is: there *is* a
rule, so while there would certainly be an issue to solve if there
weren't, there is, so there isn't :-)

>> Maybe, but in the end it's not really a tree model; it's a path model.
>> When you include modules in classes, you're inserting them in the
>> method look-up path of instances of those classes.
>
> It is a tree model (if you take only class hierarchy; with modules it's
> a network). The method lookup path is a path in the tree from the class
> of the object whose method was called (the class is a node) to the
> superclass where the method is defined (also a node). "The object
> doesn't see (...) forks in the road" because, in a tree, there is
> always only one choice of parent node.

Like I said, I'm taking an object's-eye view.  Every path is a tree, I
suppose, in the sense that one can deviate from it :-)  I know what
you mean, though.

> unsuitable for what you do (I know nothing about domain modeling)?
I don't think anyone came up with a strictly technical, bullet-proof
objection to class/module unification when Mathieu was advocating it.
Basically, if all the modules in the lookup-path were, instead,
classes, I don't think anything we can do now would be impossible
(assuming the lookup rules were preserved).  In that sense the
presence of the difference is more a matter of semantic enrichment
than technical extension.


David
31e038e4e9330f6c75ccfd1fca8010ee?d=identicon&s=25 Gregory Brown (Guest)
on 2007-09-25 22:48
(Received via mailing list)
On 1/12/07, Helder Ribeiro <helder@gmail.com> wrote:

> That is, the exact same thing happens when you have a class include two
> modules and both implement the 'hello' method. There is no self-evident
> way of choosing, so you have to come up with an arbitrary choice like
> that of order of call to 'include'.

Yes, this is true.

However the issue is rarely with immediate dependencies, but dependency
chains.

I.e., with mixins,

If I have A->B->C and C mixes in D, then E

the lookup is C,E,D,B,A

which logically is quick intuitive if you think about it.

If I have A->B->C

and  ?->D->C

and

?->E->C

Those two question marks represent two independent dependency chains
that you cannot be sure what they implement without knowing the
ancestors of each.

Since modules live outside of the hierarchy, you will only be likely
to run into this problem with bad design.  The point of mixins (and
multiple inheritance) really, is to address orthogonal concerns.  Name
collision is a sign of either a code smell, or just a really complex
system that is going to need a lot of thought to begin with.
1caf2caa2872edcb15be0e52fd442bab?d=identicon&s=25 Per Velschow (Guest)
on 2007-09-25 22:52
(Received via mailing list)
> This is interesting. Does Ruby allow codeless methods in a module like
> those of an java interface?

That wouldn't make sense. The only reason for having methods defined
with no code is when you have static type checking as in Java. In Ruby
everything happens at run-time.
F819599bbed80f48013d5acad012a9c3?d=identicon&s=25 Helder Ribeiro (helder)
on 2007-09-25 22:52
(Received via mailing list)
Hi!

dblack@wobblini.net escreveu:

>
> I'm not sure you really mean class method here.  What you're saying is
> true of any time you send a message to an object -- that is, it looks
> in its class, then the modules, etc.

Yes, i meant any method call. But I haven't found this lookup order
stated in its full anywhere else. The part after the "*and*" is what I
inferred from what the PickAxe says about the other cases (the quote is
in this thread somewhere).

> name.  This search always takes place along an unambiguous, one-track
> path.  The object doesn't see trees or forks in the road.

Yes, that's precisely what I said. I'll rephrase it:

I see no difference between having Modules or having Multiple
Inheritance (although I guess there must be and the difference between
them is the answer I'm trying to find). The problem Gregory Brown
pointed out with M.I. I have claimed to exist still with Modules.
["A->B->C can be the class hierarchy while ?->D->C and ?->E->C are
module hierarchies"; discussion above in this thread].

The only difference I could think of is that, when you have A->C and
B->C ("->" here meaning "is inherited by" or "is mixed into") and both
have a method with the same name, the conflict you would have with A
and B being classes - since they have equal rank in the hierarchy -
doesn't exist when B is a module, because modules have lower priority.

But this is an artificial difference, because you can define a lookup
order to solve this conflict without the need for Modules. So the
question is

"since Ruby already has a well-defined lookup order that takes care of
conflicts in class/module hierarchies, couldn't you have a similarly
well-defined lookup order for Multiple Inheritance and do away with
Modules altogether?"

> There's still the possibility of name collision with mixins, but there
> are (to my knowledge) no special cases, no need for tie-breaking rules
> -- because the rules that are there in the first place make a tie
> impossible.

Don't understand what you're saying. There is, indeed, no need for
tie-breaking rules if you have lookup order rules (i'm assuming those
are what you mean by "the rules that are there"). It happens that they
are the same, though, you're just giving them different names.

> Maybe, but in the end it's not really a tree model; it's a path model.
> When you include modules in classes, you're inserting them in the
> method look-up path of instances of those classes.

It is a tree model (if you take only class hierarchy; with modules it's
a network). The method lookup path is a path in the tree from the class
of the object whose method was called (the class is a node) to the
superclass where the method is defined (also a node). "The object
doesn't see (...) forks in the road" because, in a tree, there is
always only one choice of parent node.

> > equivalent *and* the only problem is with the limited case of name
> > collision and that can be solved with lookup rules, where is the source
> > of contention? Why would people favor one over the other?
>
> The thing I like about modules is that I find the model a suggestive
> way of thinking about domain modeling.  I like having both a noun-like
> thing (classes) and an adjective-like thing (modules).
> Then again,
> all of this is purely in the context of Ruby; I don't inherently like
> one or the other more.

So the difference is only in the way you think about those two things
(classes and modules)? Or do they have some difference in their
inheritance behavior that makes you think multiple inheritance would be
unsuitable for what you do (I know nothing about domain modeling)?

Cheers,

Helder
This topic is locked and can not be replied to.