Will Ruby ever support multiple inheritance through classes instead of modules? This is good since it won't need modification of existing classes, and/or converting them to modules or class-module pairs before they are inherited by a new subclass with the use of include when we reuse them. class StableClassA puts :A end class StableClassB puts :B end class Inheritor < A, B # won't work puts :A puts :B end # To make things work: module StableModuleA puts :A end class StableClassA include StableModuleA end module StableModuleB puts :B end class StableClassB include StableModuleB end class Inheritor include StableModuleA include StableModuleB puts :I end
on 2012-11-03 08:21
on 2012-11-03 12:57
I think I can say "no" with a fair amount of confidence. Single-inheritance is considered a good thing (and MI has many pitfalls), too: http://www.artima.com/intv/tuesday2.html
on 2012-11-04 12:49
Arlen Cuss wrote in post #1082618: > I think I can say "no" with a fair amount of confidence. > > Single-inheritance is considered a good thing (and MI has many > pitfalls), too: http://www.artima.com/intv/tuesday2.html Thanks for the reply. The information is adequate. It's quite disappointing though since because of that we tend to use class-module pair format just to make class ready for multiple-inheritance by mixins through its module; or else we always had to rewrite an existing class or transfer its contents to a module or the inheriting class itself every time we make use of the features. I believe MI is not that evil and its potential is the one that's more to consider or look upon. Some languages also had their ways with dealing with those problems: https://en.wikipedia.org/wiki/Multiple_inheritance. I honestly think that Ruby would have been more enjoyable if it had supported pure multiple inheritance.
on 2012-11-04 13:26
Even though other languages handle multiple inheritance without any problems they each handle it in different ways which can lead to subtle bugs when moving from one language to another. Some languages have even changed how they handle multiple inheritance between versions (Python springs to mind here, multiple inheritance got 'clarified' at one point - or so my memory tells me). There is only one way to do single inheritance and this is a good thing. Coming from languages that allow for multiple inheritance I must say I have yet to encounter a situation where I have said "this would be so much easier with multiple inheritance"
on 2012-11-04 14:07
Peter Hickman wrote in post #1082748: > Even though other languages handle multiple inheritance without any > problems they each handle it in different ways which can lead to subtle > bugs when moving from one language to another. Some languages have even > changed how they handle multiple inheritance between versions (Python > springs to mind here, multiple inheritance got 'clarified' at one point > - or so my memory tells me). Good points but think they're really not that essential, especially if it's only about one language and just the use of it. > There is only one way to do single inheritance and this is a good thing. Considering the capabilities of multiple inheritance and some situations where single inheritance don't apply and needs workarounds - like when you make a class that needs to inherits a class from an external library but also needs to inherit its natural parent class whereas you had no choice but to just include the contents of the natural parent class to it - I believe that's not always true. > Coming from languages that allow for multiple inheritance I must say I > have yet to encounter a situation where I have said "this would be so much easier with multiple inheritance" Perhaps but please consider the example situations I gave. I doubt that solutions could always be done without redundancy either by code or by work while not sacrificing consistency among classes and not using workarounds.
on 2012-11-04 14:23
Well the example you gave at the head of this thread is pretty meaningless. It is always possible to create a convoluted problem that is hard to implement in any language. My experience in not finding a need for multiple inheritance comes from writing code that people will pay for. No one has presented my with a genuine problem (as opposed to a puzzle problem) where single inheritance was inadequate. I'm not saying that they don't exist but as problems go I have yet to encounter one. YMMV
on 2012-11-04 14:46
Peter Hickman wrote in post #1082753: > Well the example you gave at the head of this thread is pretty > meaningless. Depends on one's principles. Also, perhaps it's all because I just wanted to give a brief example. I could give real situation examples but I find that unnecessary. Also please try to give attention and not evade the details I give at least for the sake of keeping this thread discussion shorter. > It is always possible to create a convoluted problem that is hard to > implement in any language. My experience in not finding a need for > multiple inheritance comes from writing code that people will pay for. No one has presented my with a genuine problem (as opposed to a puzzle problem) > where single inheritance was inadequate. It's not always about as-long-as-it-works theories. Using workarounds is not that bad, probably, but sometimes they're too fixed, too hard to apply, or too heavy by size that it could have been easier if one feature was available. It also depends on how you love the design of your craft. Not all projects are made for the sake of monetary profit. Not that I'm saying it's all about craftiness. Simplicity though safe doesn't always yield simple results. Sometimes due to its limits a more complex output is made.
on 2012-11-04 15:50
Ok then lets return to your puzzle problem. Given the first example that doesn't work. Well done you wrote some code that is invalid Ruby, guess what, you can do that in any language even if it has multiple inheritance. Now your second example, why did you write it that way? There is no need for StableClassA or StableClassB. Throw them away and nothing changes as Inheritor does not inherit from either of them. Here's the code that works the same, it is written as any Ruby programmer would write it. module StableModuleA puts :A end module StableModuleB puts :B end class Inheritor include StableModuleA include StableModuleB puts :I end Notice how it looks like the first (broken) example but with modules not classes. Notice also how it actually works. Can you now explain what advantages multiple inheritance is supposed to have over the code given here? This is why puzzle problems suck. Just give a real problem that is better solved by multiple inheritance and you will have proven your point.
on 2012-11-04 15:56
Peter Hickman wrote in post #1082761: > Ok then lets return to your puzzle problem. Given the first example that > doesn't work. Well done you wrote some code that is invalid Ruby, guess > what, you can do that in any language even if it has multiple > inheritance. Yeah I noticed that I didn't place them in methods and directly used puts instructions. It's pretty obvious. So what about it? > Now your second example, why did you write it that way? There is no need > for StableClassA or StableClassB. Throw them away and nothing changes as > Inheritor does not inherit from either of them. Here's the code that > works > the same, it is written as any Ruby programmer would write it. Sigh. I was hoping you had understand the essence of this post already. StableClassA and StableClassB is meant to be used as standalone and working classes as well. They're not just inherited as virtual, abstract or incomplete classes. > module StableModuleA > puts :A > end > > module StableModuleB > puts :B > end > > class Inheritor > include StableModuleA > include StableModuleB > puts :I > end > > Notice how it looks like the first (broken) example but with modules not > classes. Notice also how it actually works. > > Can you now explain what advantages multiple inheritance is supposed to > have over the code given here? > > This is why puzzle problems suck. Just give a real problem that is > better > solved by multiple inheritance and you will have proven your point. Try to reconsider things again from my reply which is meant to be obvious actually. Turns out you really don't have the idea. I'm guessing we'll be going through the details bit by bit before you fully understand what I mean.
on 2012-11-04 17:16
On 4 November 2012 14:57, Ross Konsolebox <lists@ruby-forum.com> wrote: > Turns out you really don't have the idea. I'm guessing > we'll be going through the details bit by bit before you fully > understand what I mean. > > Provide working code in the language of your choice that demonstrates a problem that is better served by multiple inheritance than single inheritance and you will have proven your point.
on 2012-11-04 17:55
Peter Hickman wrote in post #1082774: > Provide working code in the language of your choice that demonstrates a > problem that is better served by multiple inheritance than single > inheritance and you will have proven your point. I believe I had explained enough. If it's about examples there are many around the web. If one is interested to know more about the advantages of having multiple inheritance there certainly are many around the web. It's not that I can't prove anything. I already encountered two situations twice and both were related to inheriting an external class where one of the other parent class was already a working class - that which could have solved things simpler and easier if MI was possible. Come to think of it I could actually give you a summary of those classes. Updater OneTimeUpdater < Updater DaemonUpdater < Updater Then the utility was stable. After some time I decided to port it. ServiceUpdater < DaemonUpdater, Daemon (External Class) And this time this was not possible. I now have to decide whether I have to merge all codes from Updater to DaemonUpdater to make it work with ServiceUpdater or use another Class to Inherit Daemon that would control ServiceUpdater which would really be a hassle design-wise. No matter how you look at multi-inheritance would be the easiest form. Other variations would be just workarounds or redundant forms. Now please reconsider again if you're going to question if my analogy with respect to the matter wasn't really that deep that there could have been something I missed for you to question me again. This is also just an example. An enough proof of concept as I could see it.
on 2012-11-04 20:45
On 4 November 2012 16:55, Ross Konsolebox <lists@ruby-forum.com> wrote: > Peter Hickman wrote in post #1082774: > > Provide working code in the language of your choice that demonstrates a > > problem that is better served by multiple inheritance than single > > inheritance and you will have proven your point. > > I believe I had explained enough. If it's about examples there are many > around the web. I have googled and cannot find an example of a problem that is better served by multiple inheritance than single inheritance. If you know of one then I would be grateful if you could provide the url. > If one is interested to know more about the advantages > of having multiple inheritance there certainly are many around the web. > Now you are avoiding the question. I am well aware of the advantages of multiple inheritance, that is not what I asked. What I asked for was "a problem that is better served by multiple inheritance than single inheritance". You have not provided one and therefore any hand wavy arguments you put forward only serve to convince me that you do not know of even a single instance. > It's not that I can't prove anything. Good, then show me the code. > Come to think of it I could actually give you a summary of those > classes. > > Updater > OneTimeUpdater < Updater > DaemonUpdater < Updater > > Again with the hand waving. Without seeing the code I am unable to see how this could be refactored to make it easily implemented with single inheritance. Likewise I cannot see how difficult it might be and go "oh he's right, this would be easier with multiple inheritance". Of course I could just take you word for it ... never gonna happen
on 2012-11-04 21:05
Hi,
In message "Re: Support for multiple Inheritance by classes"
on Mon, 5 Nov 2012 01:55:36 +0900, Ross Konsolebox
<lists@ruby-forum.com> writes:
|Updater
|OneTimeUpdater < Updater
|DaemonUpdater < Updater
|
|Then the utility was stable. After some time I decided to port it.
|
|ServiceUpdater < DaemonUpdater, Daemon (External Class)
As a general principles, multiple inheritance can be replaced by
modules+mix-in.
|And this time this was not possible. I now have to decide whether I have
|to merge all codes from Updater to DaemonUpdater to make it work with
|ServiceUpdater or use another Class to Inherit Daemon that would control
|ServiceUpdater which would really be a hassle design-wise. No matter how
|you look at multi-inheritance would be the easiest form. Other
|variations would be just workarounds or redundant forms.
It might be "work around". But you have to pay the price of
inheritance graph complexity and resolving conflicts anyway.
Do you fully understand C3 algorithm that CLOS uses to resolve
multiple inheritance priority order. I don't. That's one of the
reason I didn't put multiple inheritance in to Ruby.
So, you have options. a) Use mix-ins, compromising "work around".
b) just go to a language with multiple inheritance.
matz.
on 2012-11-04 22:29
On Sun, Nov 4, 2012 at 4:49 AM, Ross Konsolebox <lists@ruby-forum.com>wrote: > Thanks for the reply. The information is adequate. It's quite > disappointing though since because of that we tend to use class-module > pair format just to make class ready for multiple-inheritance by mixins > through its module; or else we always had to rewrite an existing class > or transfer its contents to a module or the inheriting class itself > every time we make use of the features. > What you're basically saying here is we can get most of the properties of multiple inheritance from mixins. That's good! MI vs. mixins is a philosophical debate. Mixins are a much simpler, more easy-to-reason-about model than true multiple inheritance, IMO. MI brings with it all sorts of odd corner cases, such as the Diamond Inheritance Problem: http://en.wikipedia.org/wiki/Multiple_inheritance#... So what you view as a weakness I see as a strength. > I honestly think that Ruby would have been more enjoyable if it had > supported pure multiple inheritance. If you really want a Ruby-like language with multiple inheritance, might I suggest Python?
on 2012-11-05 04:44
Tony Arcieri wrote in post #1082793: > If you really want a Ruby-like language with multiple inheritance, might > I > suggest Python? I haven't used Python for quite a while now. Python supports multiple inheritance? Wow..... Bill
on 2012-11-05 10:32
Multiple Inheritance is the GOTO statement of object oriented programming -- sort of a caveat emptor to people new to the paradigm coming from a procedural language background. Module/mix-in would work as far as conceptually. If it's a daemon, as the so called example used, a system level service. The paradigm changes. In UNIX not everything is an object. Formally taught to sysadmins that everything is a file which really really means everything is a stream of bytes( i.e. C Programming and system kernel/shell)... This is why Kernel in ruby is a module and not a class. I can't think of one reason why multiple inheritance would be useful for daemon process. Updating based on changes can be accomplished through creating wrappers to the signals much the same way rc.d/init.d is. Inside ruby you have access to message passing much the same as you would expect from any object oriented language. Ultimately there is nothing wrong with wanting a feature. Consider it a challenge to work within the context of the language or hack up your own dsl. MI is not the panacea that early oops language designers thought it would be. There most certainly is a better way to deal with various problems and solutions. Also it's not a "work around" to use Mix-in Modules as the op suggested. It's actually the preferred and correct way i.e. the Ruby way. Hit up a couple non object oriented languages and move data back and forth there. That is the only way to gain enough insight to know what is a "work around" vs the concept of "working with". The limitations are not with the ruby language or interpreter. It's with the users who superimposes such limitations upon themselves. For one reason or another this thread reminded me of the Execution In Kingdom of Nouns http://steve-yegge.blogspot.com/2006/03/execution-...
on 2012-11-05 12:20
Thank you everyone for giving their attention and thoughts to the thread, especially Yukihiro-san. It's truly an honor. I believe my question has been answered already and discussing advantages and disadvantages of multi-inheritance over single-inheritance with aid of modules is another thing. Hearing everyone's thoughts especially the master, I think I would just accept and respect Ruby the way it is, save that someday I might make a personal extension of it if I'm able, well not really. Thanks again. I actually imagined this: class Ruby inherit Multiple inherit Inheritance end Just my thoughts. Cheers, Ross
on 2012-11-05 13:34
On Sun, Nov 4, 2012 at 12:49 PM, Ross Konsolebox <lists@ruby-forum.com>wrote: > or transfer its contents to a module or the inheriting class itself > every time we make use of the features. > If you notice you do this regularly you are probably doing something wrong with regard to Ruby's OOP. It looks as if you want to carry over your inheritance scheme from language X (C++, Eiffel...). If something is an entity (class) _and_ a set of functionality used in various places (module) at the same time then maybe you do not separate the two clear enough. For example, you might notice that your reported 1:1 relationship between class and module should rather be a 1:4 relationship (i.e. an entity being built from various functionalities). Or maybe you are using inheritance where you should rather use composition. All that could of course be discussed much better with a concrete example of your code... :-) > I believe MI is not that evil and its potential is the one that's more > to consider or look upon. Some languages also had their ways with > dealing with those problems: > https://en.wikipedia.org/wiki/Multiple_inheritance. > > I honestly think that Ruby would have been more enjoyable if it had > supported pure multiple inheritance. > For me absence of class MI does not take anything away from the fun and I can't imagine how it could be more fun with class MI. I tend to believe though that inheritance is generally overrated. For me encapsulation is a much more important concept in OOP than inheritance. Kind regards robert
on 2012-11-05 17:13
Holy smoke! What is going on here?!? If you have ever used a Ruby module as a mixin then you've used multiple inheritance. Period. There's no wiggle room. What is a mixin in Ruby is part, only part, of what a general multiple inheritance mechanism provides in other languages. And I'll bet that most of you who have used mixins thought they worked out pretty well. So. You've used multiple inheritance and thought it was a good thing. WHY the near universal contempt for multiple inheritance? What's up? Cheers, Bob
on 2012-11-05 18:44
> If you really want a Ruby-like language with multiple > inheritance, might I suggest Python? What I do not understand is why people suggest other languages. It is not as simple. Python uses so many different ways, it has a completely different philosophy, so suggesting to use another language A because you do not like one component in language B isn't any real improvement. Via modules in ruby you can get quite close to what multiple inheritance solves. There is no need to go to python at all. Ruby and Python are way too similar in their ecological niche as well. There is one thing that is however not looked at much at all in this discussion - less the distinction between multiple inheritance vs. module mixins, and much more so what the distinction class vs. module actually serves. Because I often feel that the distinction between classes and modules is much more arbitrary than seems to be reasonable. You have a class Foo, and you mixin three different modules into it. That is quite close to what multiple inheritance does too, just not following the classical subclassing tree. But why is that behaviour contained within a module? Why could we not assume that ALL behaviour of every object resides in an (perhaps invisible) module? Then we could use classes the same way as modules. module Foo end module Bar include Foo end vs. class Foo end class Bar < Foo end To me this is a distinction in Ruby that I do not really feel is compelling at all. I have seen people use class Foo module Bar end end And I asked them why they did it that way, and they told me that the toplevel class gives them more features, namely the ability to do Foo.new, than it would by using a module. That baffled me when I heard it. My question thus is: Why must there be this distinction between classes and modules in this way?
on 2012-11-06 22:04
On Mon, Nov 5, 2012 at 6:44 PM, Marc Heiler <lists@ruby-forum.com> wrote: > There is one thing that is however not looked at much at > all in this discussion - less the distinction between > multiple inheritance vs. module mixins, and much more so > what the distinction class vs. module actually serves. > > Because I often feel that the distinction between classes > and modules is much more arbitrary than seems to be reasonable. > The difference between class and module in Ruby is - classes can be instantiated, modules can't - classes can be inherited (SI), modules can be included (MI) Did I miss any? Other than that both are identical (e.g. both can be used as namespace). For me the more dramatic difference is actually the first one because despite the differences between SI and MI in Ruby it's just gradual (i.e. the number of items to inherit from - 1 for classes, n for modules). So if we assume for a moment that we agree on the most significant difference then it follows quite naturally (for me at least) that classes should be used for entities, tangible things while modules should rather be used for capabilities (behavior). And I believe you can see that distinction at work in the standard library: there's Array which is a list of objects (entity) and Enumerable which is a set of capabilities. > But why is that behaviour contained within a module? Why > could we not assume that ALL behaviour of every object > resides in an (perhaps invisible) module? > > Then we could use classes the same way as modules. > I do not understand how this follows from the premise. If all behavior would reside in modules than classes would not contain behavior at all. But then classes and modules could not be used the same way. What am I missing here? > Why must there be this distinction between classes and > modules in this way? > I do not think there is a reason why the distinction "must" be there. It's just what Matz designed the language to be. I think the distinction I was trying to make above is actually not too unreasonable. It seems so far it has served the language quite well so far. Kind regards robert
on 2012-11-07 10:34
I found this answer quite reasonable from this book: http://ruby.learncodethehardway.org/book/ex44.html . The question of "inheritance vs. composition" comes down to an attempt to solve the problem of reusable code. You don't want to have duplicated code all over your code, since that's not clean and efficient. Inheritance solves this problem by creating a mechanism for you to have implied features in base classes. Composition solves this by giving you modules and the ability to simply call functions in other classes. If both solutions solve the problem of reuse, then which one is appropriate in which situations? The answer is incredibly subjective, but I'll give you my three guidelines for when to do which: Avoid meta-programming (multiple inheritance) at all costs, as it's too complex to be useful reliably. If you're stuck with it, then be prepared to spend time finding where everything is coming from. Use composition to package up code into modules that is used in many different unrelated places and situations. Use inheritance only when there are clearly related reusable pieces of code that fit under a single common concept, or if you have to because of something you're using. However, do not be a slave to these rules. The thing to remember about object oriented programming is that it is entirely a social convention programmers have created to package and share code. Because it's a social convention, but one that's codified in Ruby, you may be forced to avoid these rules because of the people you work with. In that case, find out how they use things and then just adapt to the situation.
Please log in before posting. Registration is free and takes only a minute.
Existing account
(Switch to SSL-encrypted connection)
NEW: Do you have a Google/GoogleMail or Yahoo account? No registration required!
Log in with Google account | Log in with Yahoo account
Log in with Google account | Log in with Yahoo account
No account? Register here.