inheritance concept in ruby

Discussion in 'Ruby' started by Kumar Tnj, Jan 9, 2007.

  1. Kumar Tnj

    Kumar Tnj Guest

    Hi,

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

    Thanks & Regards,
    Kumar

    --
    Posted via http://www.ruby-forum.com/.
     
    Kumar Tnj, Jan 9, 2007
    #1
    1. Advertising

  2. Kumar Tnj

    hemant Guest

    On 1/9/07, Kumar Tnj <> 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.



    --
    gnufied
    -----------
    There was only one Road; that it was like a great river: its springs
    were at every doorstep, and every path was its tributary.
     
    hemant, Jan 9, 2007
    #2
    1. Advertising

  3. On 1/9/07, Kumar Tnj <> 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.
     
    Wilson Bilkovich, Jan 9, 2007
    #3
  4. Wilson Bilkovich wrote:
    > On 1/9/07, Kumar Tnj <> 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.


    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
     
    Helder Ribeiro, Jan 12, 2007
    #4
  5. On 1/11/07, Helder Ribeiro <> 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.
     
    Gregory Brown, Jan 12, 2007
    #5
  6. On 1/11/07, Helder Ribeiro <> wrote:
    >
    > Wilson Bilkovich wrote:
    > > On 1/9/07, Kumar Tnj <> 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.

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


    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.
     
    Wilson Bilkovich, Jan 12, 2007
    #6
  7. Wilson Bilkovich wrote:
    > >

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


    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... classes and modules?"&hl=en#fd1ae73662ff8916

    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
     
    Helder Ribeiro, Jan 12, 2007
    #7
  8. On 1/12/07, Helder Ribeiro <> 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.
     
    Gregory Brown, Jan 12, 2007
    #8
  9. On 1/12/07, Helder Ribeiro <> 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.
     
    Gregory Brown, Jan 12, 2007
    #9
  10. Kumar Tnj

    Per Velschow Guest

    > 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.
     
    Per Velschow, Jan 12, 2007
    #10
  11. On Jan 12, 3:45 pm, "Per Velschow" <> 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
     
    Gregory Brown, Jan 12, 2007
    #11
  12. Gregory Brown wrote:
    > On 1/12/07, Helder Ribeiro <> wrote:
    >
    > (...) 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.


    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
     
    Helder Ribeiro, Jan 15, 2007
    #12
  13. Kumar Tnj

    Guest

    Hi --

    On Mon, 15 Jan 2007, Helder Ribeiro wrote:

    > Gregory Brown wrote:
    >> On 1/12/07, Helder Ribeiro <> wrote:
    >>
    >> (...) 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.

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


    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.

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


    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.

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


    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

    --
    Q. What is THE Ruby book for Rails developers?
    A. RUBY FOR RAILS by David A. Black (http://www.manning.com/black)
    (See what readers are saying! http://www.rubypal.com/r4rrevs.pdf)
    Q. Where can I get Ruby/Rails on-site training, consulting, coaching?
    A. Ruby Power and Light, LLC (http://www.rubypal.com)
     
    , Jan 15, 2007
    #13
  14. Hi!

    escreveu:

    > On Mon, 15 Jan 2007, Helder Ribeiro wrote:
    >
    > > 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.

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

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


    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.

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


    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.

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

    >
    > 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
     
    Helder Ribeiro, Jan 16, 2007
    #14
  15. 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 <> 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?


    > > 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)?


    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.
     
    Gregory Brown, Jan 20, 2007
    #15
  16. Kumar Tnj

    Guest

    Hi --

    On Wed, 17 Jan 2007, Helder Ribeiro wrote:

    > 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?"


    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 :)

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

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

    >> 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)?


    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

    --
    Q. What is THE Ruby book for Rails developers?
    A. RUBY FOR RAILS by David A. Black (http://www.manning.com/black)
    (See what readers are saying! http://www.rubypal.com/r4rrevs.pdf)
    Q. Where can I get Ruby/Rails on-site training, consulting, coaching?
    A. Ruby Power and Light, LLC (http://www.rubypal.com)
     
    , Jan 20, 2007
    #16
  17. Gregory Brown wrote:
    > On 1/16/07, Helder Ribeiro <> 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/browse_thread/thread/dbe4fc8bea8ef1f8/#

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

    >
    > This is mostly a style thing.
    >
    > 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.


    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
     
    Helder Ribeiro, Jan 23, 2007
    #17
  18. 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
     
    Helder Ribeiro, Jan 23, 2007
    #18
  19. Kumar Tnj

    Guest

    On Jan 23, 2007, at 10:35 AM, Helder Ribeiro wrote:

    > 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 :)



    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
     
    , Jan 23, 2007
    #19
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. maxw_cc
    Replies:
    1
    Views:
    3,145
    Martijn van Steenbergen
    Dec 21, 2003
  2. cppsks
    Replies:
    0
    Views:
    827
    cppsks
    Oct 27, 2004
  3. karthikbalaguru
    Replies:
    9
    Views:
    1,041
  4. Daniel Pitts
    Replies:
    27
    Views:
    1,907
    Mike Schilling
    Feb 27, 2008
  5. Iñaki Baz Castillo

    Pointer concept in Ruby ?

    Iñaki Baz Castillo, Apr 24, 2008, in forum: Ruby
    Replies:
    11
    Views:
    270
    Iñaki Baz Castillo
    Apr 25, 2008
Loading...

Share This Page