Re^4: Understanding 'Multiple Inheritance'
by dragonchild (Archbishop) on Mar 07, 2005 at 13:43 UTC
|
You knew someone was going to reply from the P6 aspect, right? Please tell me you did! :-)
Implement the MI such that it redispatches any method that returns a 'Not processed' code. If the first (by some defintion) subclass implementing the method returns this value, the method is redispatched to the next subclass that implements it, until one of them responds saying 'Okay, I've got that one'.
Coincedentally, that's exactly (well, almost) how Perl6 will implement it. The method dispatcher will ask all the classes involved (in some order you the programmer get to specify) who wants to handle it. Each class can be written with that in mind or they can just handle it and be selfish. But, the mechanism will exist.
The real problem with the CD player / Radio example is a that the problem was ill-conceived. A CD-player / Radio shouldn't be viewed as both is-a a CD-player and a Radio. Those items aren't the true atomic concepts as a CD-player and a Radio are each several items. A better view would be a pipeline of objects that provide for a plugin mechanism. So, you would have
- Output(s)
- MusicMaker(s)
- Control(s)
- PowerSupply(s)
Then, you build it like you have a bunch of Legos, which is how they're built in the real world. And, you do have mode switches for most of those categories which switches the active FOO from A to B. In other words, the actual physical item is built with composition, but the Foobars each inherit from some base Foobar for an interface and some common implementation bits.
Being right, does not endow the right to be rude; politeness costs nothing. Being unknowing, is not the same as being stupid. Expressing a contrary opinion, whether to the individual or the group, is more often a sign of deeper thought than of cantankerous belligerence. Do not mistake your goals as the only goals; your opinion as the only opinion; your confidence as correctness. Saying you know better is not the same as explaining you know better.
| [reply] |
|
|
You knew someone was going to reply from the P6 aspect, right? Please tell me you did! :-)
Sorry, but no I didn't know. I thought someone might though:)
Each class can be written with that in mind or they can just handle it and be selfish.
In the first case, all the co-inheriters (and by extension, all possible co-inheritors, which is another way of saying: "every class that ever might be inherited from.") have to consider the possibility, and handle it.
In the second case, you have to add a mechanism to the language to allow the superclass writer to hand code the inheritance/dispatch ordering. But do you do that:
In any case, I think that roles (if they turn out to be what I think they should be) will obviate the need for the above manually controllable dispatch ordering and render MI a little used feature.
The real problem with the CD player / Radio example is a that the problem was ill-conceived.
However, I did know that this objection would come up :)
The problem is that hindsight is 20:20, but you can neither buy it, nor be taught it--nor inherit it:). You can only acquire it with time, and by then it is too late.
When the radio was invented, the CD wasn't even Sci-Fi material. And yes, I know I have stretched the analogy too far, but it does hold.
In order for your sub-elemental design to work, you need to have the entire problem laid out up-front--or spend an inordinate amount of time speculating what the future might hold.
Taking the analogy a little further. You've designed and implemented your componentised system. It works great. Then you get the requirement legislated upon you to support a new technology that turns sound into 'pictures' that the deaf can 'hear'.
The problem is that 'tone' controls for this technology need to mix components of both the left and right audio channels according to a bizarre (in audio terms) function so that the tone control varies the definition of the 'picture' in a 3-dimensional way. Further, the volume control needs to vary the range of colours in which the overall 'picture' is presented in. But, because deaf people also suffer the same visual maladies that other sighted people suffer--colour-blindness; short-sightedness etc.--it also becomes necessary to be able to limit the range of colours over which the volume is spread to some sub-range of the total possible to ensure they remain within the visual accuity of the user.
That is Sci-Fi as far as I am aware, but the point is that there is no way to know now, when that requirement will become a reality, or what constraints and requirements it will impose upon existing systems. Trying to define your componentisation now, such that it will allow for their inheritable inclusion into that (and all other) future systems is an impossible task. So don't try!
Design you system, and it's components to deal with todays requirements and realities--and no more. That allows you to keep it as clean and light as is practible now. It may mean that a future system that incorporates it (through composition) will be more bulky and need to actively override (rather than pass through) more elements than might otherwise be the case had you been able to design with that new system in mind.
But it also means that all the other uses of it without those special ancillary requirements did not have to bear the costs of the speculative possibilities.
If the composite system with the special requirements proves to be too heavy, inefficient or laborious, then the subsystems it uses will need to be reworked or re-designed from scratch with the new requirements in mind, but either way, the rework will now know what those new requirements are, and will be able to make specific decisions based upon them.
Any speculative extras added into the original design might preclude that re-working, but then again, they may not. And history favours the latter. In that case, all those speculative extras in the original design simply burdened all the uses of that design that didn't use them, and all the design and implementation that went into them was wasted. Indeed, it may well be that it was the very presence of those extras that forced the re-working.
Designing your 70's TV with a press-out slot for a Beta-Max video tape may have seemed like a good bet at the time, but ultimately would have been a bad decision :)
Examine what is said, not who speaks.
Silence betokens consent.
Love the truth but pardon error.
| [reply] |
|
|
Except my system already handles that. You have an output system that is pipelined with the music-maker and the controls. The controls will say to the speakers "Please increase the volume from 5 to 6". The music-maker will say to the speakers "Please output the following sounds". The speakers will then do what they feel is appropriate with what they receive. Pictures, sound, smells ... I don't care. The pipeline has done what it was supposed to do - pass requests back and forth.
Now, it may be appropriate to create an aggregate class to deal with the speakers. But, that aggregate class will conform to the same API as a standard speaker, so it's a drop-in replacement - a plug-in, so to speak.
Being right, does not endow the right to be rude; politeness costs nothing. Being unknowing, is not the same as being stupid. Expressing a contrary opinion, whether to the individual or the group, is more often a sign of deeper thought than of cantankerous belligerence. Do not mistake your goals as the only goals; your opinion as the only opinion; your confidence as correctness. Saying you know better is not the same as explaining you know better.
| [reply] |
|
|
|
|
| [reply] |
|
|
I wanted to reply to the issues you raised with P6's handling of multimethod dispatch.
In the first case, all the co-inheriters . . . have to consider the possibility, and handle it.
Actually, they don't. There will be a usable set of default behaviors. And, just like in all things, you only have to define something if you don't like the default. If you like it, don't redefine it! (As an aside, I wish people would follow this advice for most overloaded stuff. If you have a random numeric overloaded object that doesn't subtract when adding or some other goofiness, just define numify, set fallback to true, and let Perl handle the rest.)
you have to add a mechanism to the language to allow the superclass writer to hand code the inheritance/dispatch ordering.
And, since Larry wants it, Larry's gonna get it. Re-read A12 for how he will do this. The short version is you'll get to do it in all the places you mention, and more.
In any case, I think that roles (if they turn out to be what I think they should be) will obviate the need for the above manually controllable dispatch ordering and render MI a little used feature.
Absolutely! There will be little need for MI at all, once roles/traits/mixins/etc/etc/ad-nauseum are grokked. But! (and there's always a but) . . . in those random cases where MI is actually the easier WTDI, then you will have the option. Remember - roles/traits/whatever are really a generalization of multiple inheritance without all the bagage that MI comes with through single inheritance.
Being right, does not endow the right to be rude; politeness costs nothing. Being unknowing, is not the same as being stupid. Expressing a contrary opinion, whether to the individual or the group, is more often a sign of deeper thought than of cantankerous belligerence. Do not mistake your goals as the only goals; your opinion as the only opinion; your confidence as correctness. Saying you know better is not the same as explaining you know better.
| [reply] |
|
|
You need to break up the design more cleanly.
by skyknight (Hermit) on Mar 07, 2005 at 14:28 UTC
|
As DragonChild suggests, you ought to take a more component oriented
approach, assembling the final product from base components.
I would probably have something along the lines of the following
classes: CDPlayerInterface, RadioInterface, AudioDeviceInterface,
CDPlayer, Radio, and RadioCDCombo. The Radio class would be a
marriage of the RadioInterface and AudioDeviceInterface, the CDPlayer
class would be a marriage of the CDPlayerInterface and the
AudioDeviceInterface, and the RadioCDCombo class would be a marriage
of CDPlayerInterface and RadioInterface and AudioDeviceInterface.
Or something like that... I'm not sure I like the specifics of
my solution, but I think the general paradigm is better.
| [reply] |
|
|
| [reply] [d/l] |
|
|
you ought to take ...
Ah, the classical fallacy. Whenever someone raises an objection against use of inheritance, or multiple inheritance, someone is bound to step up and say you should have redesigned your entire inheritance tree differently.
Well, then you have missed one of the important aspects of OO: code reuse and encapsulation. You want to be able to take an existing Radio class, and an existing CDplayer class, and combine them into a Radio/CDplayer. Regardless how the Radio class and the CDplayer class are implemented. Hopefully, they are build using smaller units, and if I'm lucky, they share some parts as well. But ultimately, for me, as the constructor of the Radio/CDplayer, it shouldn't matter how the Radio and the CDplayer are implemented - that's what's encapsulation is about. I do have to care about overlap in the API - both classes may have an on method, and they both may have a volume method. My combined object probably wants two on methods (although they can't be both called 'on'), but on volume method. I do have to care about the interface, but I should not have to care about setting the volume - the inheriting classes will know.
If I can only do (multiple) inheritance properly if I'm in full control of the entire inheritance tree, OO becomes utterly useless to me. I want to reuse code. Reuse code that I haven't written, and shouldn't need to inspect.
| [reply] |
Re^4: Understanding 'Multiple Inheritance'
by doom (Deacon) on Mar 08, 2005 at 13:18 UTC
|
BrowserUk wrote:
The single biggest (and hardest) lesson I've had to learn through experience, because it was never covered on any CS course I took--nor any I have read about since--is: "Don't do it unless you have to!".
Funny, the one that I've learned is "Always be neat, even when you think you don't have to."
| [reply] |
|
|
Funnily enough, most every course I took at college, form was favoured over content.
I saw people that wrote the most boring, derivitive and unoriginal work consistantly score the highest marks because they were blessed with neat handwriting and good rote recall for spelling.
And one American girl got really upset because she would be constantly marked down by our English English teacher for "mis-spellings" like favor -v- favour, color -v- colour etc.
Her writing were damn nearly magical to most of us very parochial Brits. We loved hearing her stories of the Near and Far East, and her recounting of everyday life in West Berlin in the 70s were so far beyond our experience it was almost like SciFi. For her writing to be marked down because she had been taught to write differently to us always seemed most unfair.
This was all the more galling for her as she had gained her education all over the world. As the daughter of a USAF guy, she had travelled all over and been schooled in many countries in Europe and Asia. And the only country where she was penalised for her spelling, and expressions like "they borrowed me a cup of sugar", was the UK.
"Always be neat, even when you think you don't have to."
Reminds of a guy I was at school with. He was brilliant at woodwork. His joins were always invisible, his joints barely needed the glue, his tools always sharp, and his workbench was never covered in shavings and sawdust. He became a carpenter--and hated it.
His first commercial job was erecting shuttering. He would carefully align the edges of the boards. Every board had the same number of nails, which were always equidistantly spaced along the edges. Every nail was driven home properly with none ever being turned over. The problem was, he couldn't earn anywhere near the same amount of money as his colleagues. He was too slow and it was piecework.
Shuttering is the wooden frameworks they build to pour concrete into when they build office blocks and bridges. It's purpose is to scaffold and support whilst the concrete dries, after which it is just ripped off. It is a temporary structure that doesn't need to be neat or perfect. It simply needs to perform its function for the few hours or days that it takes for the concrete to be poured and set. And it needs to be fast and cheap.
Examine what is said, not who speaks.
Silence betokens consent.
Love the truth but pardon error.
| [reply] |
|
|
Would it have been clearer what I meant if I said
"Always be orderly, even if you think you don't have to"?
How about "Always use 'use strict', even if you think you don't have to?"
Most quests for a software methodology seem to boil down to a search for an "Always do it like this", e.g. always encapsulate (meaning, insulate the small parts from the behavior of the whole... this might or might not be done using OOP).
I would contend that every one of these principles is the enemy of strict parsimony. Should you never use encapsulation unless you know you need to, or should you always use (some form of) encapsulation, so you don't have to worry about whether you need to?
| [reply] |