Recent

Author Topic: Proposing 4 New Ideas - #3 Multiple Inheritance  (Read 5284 times)

IndigoBoy83

  • New member
  • *
  • Posts: 9
Proposing 4 New Ideas - #3 Multiple Inheritance
« on: March 22, 2019, 01:36:25 pm »
PAGE #3 - Multiple Inheritance

Below is a demonstration of the use of multiple inheritance.  The class TFace inherits both TSmile and TEyes.  With TSmile you can Start_Smiling and Stop_Smiling.  With TEyes you can Start_Crying and Stop_Crying.  Notice, when you Start_Smiling you automatically Stop_Crying, and when you Start_Crying you automatically Stop_Smiling.  So, it is impossible to have be both smiling and crying at the same time using only the given methods. 

Notice that TSmile.Stop_Crying and TEyes.Stop_Smiling are not implemented and virtual.  Within TFace, the unimplemented TSmile.Stop_Crying gets redirected to TEyes.Stop_Smiling (which IS implemented); and likewise, within TFace, the unimlplemented TEyes.Stop_Smiling gets redirected to TSmile.Stop_Smiling (which IS implemented).

Since both TSmile and TEyes have methods that are not implemented means that these classes can *never* be instantiated.  TFace can; but a variable of TSmile or TEyes cannot ever exist on its own.

Code: Pascal  [Select][+][-]
  1. Program Example_Of_Multiple_Inheritance;
  2.  
  3. interface
  4.  
  5. uses
  6.     Classes;
  7.  
  8. type
  9.     TSmile = class
  10.       smiling : boolean;
  11.  
  12.       Procedure Start_Smiling;
  13.       Procedure Stop_Smiling;
  14.       Procedure Stop_Crying; virtual;
  15.     end;
  16.  
  17.     TEyes = class
  18.       crying : boolean;
  19.  
  20.       Procedure Start_Crying;
  21.       Procedure Stop_Crying;
  22.       Procedure Stop_Smiling; virtual;
  23.     end;
  24.  
  25.     TFace = class ( TSmile, TEyes );
  26.       Procedure Stop_Crying = TEyes.Stop_Crying; virtual;
  27.       Procedure Stop_Smiling = TSmile.Stop_Smiling; virtual;
  28.     end;
  29.  
  30. Procedure TSmile.Start_Smiling;
  31. begin
  32.   writeln( 'I''m starting smiling..' );
  33.   smiling := true;
  34.   writeln( '..so I must stop crying.' );
  35.   Stop_Crying;
  36. end;
  37.  
  38. Procedure TSmile.Stop_Smiling;
  39. begin
  40.   writeln( 'I am no longer smiling.' );
  41.   smiling := false;
  42. end;
  43.  
  44. Procedure TEyes.Start_Crying;
  45. begin
  46.   writeln( 'I''m starting crying..' );
  47.   crying := true;
  48.   writeln( '..so I must stop smiling.' );
  49.   Stop_Smiling;
  50. end;
  51.  
  52. Procedure TEyes.Stop_Crying;
  53. begin
  54.   writeln( 'I am no longer crying.' );
  55.   crying := false;
  56. end;
  57.  
  58. var
  59.    MyFace : TFace;
  60.  
  61. begin
  62.   TFace.Create;
  63.  
  64.     TFace.Start_Smiling;
  65.     TFace.Start_Crying;
  66.  
  67.   TFace.Free;
  68. end.

I'm starting smiling..
..so I must stop crying.
I am no longer crying.
I'm starting crying..
..so I must stop smiling.
I am no longer smiling.
« Last Edit: March 22, 2019, 01:48:18 pm by IndigoBoy83 »

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 11382
  • FPC developer.
Re: Proposing 4 New Ideas - #3 Multiple Inheritance
« Reply #1 on: March 22, 2019, 02:01:09 pm »
We already have interface based multiple inheritance..

IndigoBoy83

  • New member
  • *
  • Posts: 9
Re: Proposing 4 New Ideas - #3 Multiple Inheritance
« Reply #2 on: March 22, 2019, 02:37:52 pm »
Isn't what I show an easier method?

Please would you write out my program Example_Of_Multiple_Inheritance using interfaces. 
I've always been unsuccessful at such attempts.
Much appreciated.

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 9791
  • Debugger - SynEdit - and more
    • wiki
Re: Proposing 4 New Ideas - #3 Multiple Inheritance
« Reply #3 on: March 22, 2019, 03:13:30 pm »
There is something odd, on how you use "virtual" on some, but not other methods. And how there is no "override" at all.
Anyway, I copied it blindly in below examples. Keep in mind that "inherited" works for none virtual methods too. So my inherited example can be made independent of what is virtual.



There are millions of discussion on the internet about multiply inheritance (MI). The conclusions go from ok to disaster. (I stick to the latter).
In any case, in most cases MI can easily be replaced by delegation. And in the long term delegation often yields the better results.

But lets first look at your example.
You are mixing several things.

MI:
Code: Pascal  [Select][+][-]
  1.     TFace = class ( TSmile, TEyes );

Shorthand to avoid writing a function body:
Code: Pascal  [Select][+][-]
  1.       Procedure Stop_Crying = TEyes.Stop_Crying; virtual;

The shorthand has nothing to do with MI. It could be done for normal classes to. (e.g. forward to a delegate class).

So if and when comparing, the above needs to be kept in mind. Only compare the MI. Do not mistake the other shorthands for MI, and advertise MI as better, because you like the shorthand.

Your example as delegation (with shorthands, so comparison stands)

Code: Pascal  [Select][+][-]
  1.     TFace = class
  2.        FSmile: TSmile;
  3.        FEyes: TEyes;
  4.        Procedure Stop_Crying = FEyes.Stop_Crying; virtual;
  5.     end;
  6.  

Of course the shorthand does not exist. So you need to write code for it.
And you also need to create FSmile and FEyes in the constructor of TFace (for that a shorthand could be found, but I would not advertise doing so).

So anyway, other than the need to create TSmile/TEyes instances (which also gives you the power to instantiate subclasses like TCrookedSmile) the above is the same amount of code.

Only with MI, if I write
Code: Pascal  [Select][+][-]
  1. procedure TFace.SomeThing;
  2. begin
  3.   inherited Stop_Crying;
  4. end;
It becomes complicated. Which baseclass should be called?

This is especially a problem, when you hadn't looked at the code in a couple of years, but need to work on it again.
With delegation, you always get explicit calls (calls on either FSmile or FEyes).


In conclusion, after taking out the shorthands:

Delegates and MI need a body for TFace.Stop_Crying. (or both can have the shorthand). => equal

Delegates need to create the delegates (and destroy them).
2 lines of code per delegate. But more flexibility, as delegates can be instances of subclasses.
In any case, if needs must a shorthand would be possible.

Delegates prevent you from ambiguous inherited calls.





devEric69

  • Hero Member
  • *****
  • Posts: 648
Re: Proposing 4 New Ideas - #3 Multiple Inheritance
« Reply #4 on: March 22, 2019, 03:21:06 pm »
My 2 cents:

that's for sure: in Pascal the multiple inheritance ***IS*** the solution for multiple inheritance (multiple inheritance of different classes as in C, does not exist). In pascal, you can define a TClass, and declare in it several thematic interfaces that will make up your class.

A tip: the interfaces reify naturally as you're writing code and you'll realize that you'll have classes that have the same thematic procedures, that do the same thing ==> you will then naturally see them, and you will extract them into the same interface, to serialize a bunch of thematic procedures.
Another trick: thinking multiple inheritance is a bit "dangerous". Rather than thinking that "an apple inherits from the sugar and from the fruit at the same time", it's better to think that "an apple is the composition of minimalist sugar and minimalist fruit together" (in any case, that's my opinion: the granularity of the correct calibration of the responsibilities of your class, is easier to achieve this way).
« Last Edit: March 22, 2019, 03:48:39 pm by devEric69 »
use: Linux 64 bits (Ubuntu 20.04 LTS).
Lazarus version: 2.0.4 (svn revision: 62502M) compiled with fpc 3.0.4 - fpDebug \ Dwarf3.

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 9791
  • Debugger - SynEdit - and more
    • wiki
Re: Proposing 4 New Ideas - #3 Multiple Inheritance
« Reply #5 on: March 22, 2019, 03:42:07 pm »
Well yes, interface is the other side to this topic

If it is not about how you build your class, but as what you want it to be seen.

That is you want to pass your TFace to a method that needs TEyes.
=> which is wrong.

A TFace should never be a TEyes. It is different.
A TFace can only be something that has Eyes. An interface does exactly that. It provide a way to pass the interface to any method that expects something with eyes.

devEric69

  • Hero Member
  • *****
  • Posts: 648
Re: Proposing 4 New Ideas - #3 Multiple Inheritance
« Reply #6 on: March 22, 2019, 03:53:31 pm »
Quote
A TFace should never be a TEyes. That's different.

+1 (inheritance = "is one `TFoo`", to which complexity is added)
« Last Edit: March 22, 2019, 03:55:05 pm by devEric69 »
use: Linux 64 bits (Ubuntu 20.04 LTS).
Lazarus version: 2.0.4 (svn revision: 62502M) compiled with fpc 3.0.4 - fpDebug \ Dwarf3.

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 9791
  • Debugger - SynEdit - and more
    • wiki
Re: Proposing 4 New Ideas - #3 Multiple Inheritance
« Reply #7 on: March 22, 2019, 04:49:50 pm »
Btw, there is another way, if you do not want interfaces. Also based on delegation.

If you have a procedure "procedure SetFocus(SomeEyes);" and you have a face:
SetFocus(Face.Eyes);

The FEyes in TFace, then could be of class "TEyesInFace = class(TEyes)" (as opposed to TEyesInVodooShop).
TEyesInFace can have an Owner of type TFace. So they can interact/depend.

--
Of course this can get real creepy:  Costumer.SetFocusOnMe(VodooShop.Eyes)
;) ;)
« Last Edit: March 22, 2019, 04:52:18 pm by Martin_fr »

Ñuño_Martínez

  • Hero Member
  • *****
  • Posts: 1186
    • Burdjia
Re: Proposing 4 New Ideas - #3 Multiple Inheritance
« Reply #8 on: March 24, 2019, 01:08:02 pm »
Isn't what I show an easier method?
There's no easy way to implement Multiple Inheritance.  You need to deal with deadly diamonds of death and that's never simple nor transparent.
Are you interested in game programming? Join the Pascal Game Development community!
Also visit the Game Development Portal

ASBzone

  • Hero Member
  • *****
  • Posts: 678
  • Automation leads to relaxation...
    • Free Console Utilities for Windows (and a few for Linux) from BrainWaveCC
Re: Proposing 4 New Ideas - #3 Multiple Inheritance
« Reply #9 on: March 24, 2019, 04:28:43 pm »
Of course this can get real creepy:  Costumer.SetFocusOnMe(VodooShop.Eyes)
 ;) ;)


 :o :D
-ASB: https://www.BrainWaveCC.com/

Lazarus v2.2.7-ada7a90186 / FPC v3.2.3-706-gaadb53e72c
(Windows 64-bit install w/Win32 and Linux/Arm cross-compiles via FpcUpDeluxe on both instances)

My Systems: Windows 10/11 Pro x64 (Current)

440bx

  • Hero Member
  • *****
  • Posts: 3944
Re: Proposing 4 New Ideas - #3 Multiple Inheritance
« Reply #10 on: March 24, 2019, 04:33:15 pm »
Some sadist with an axe to grind against programmers thought the goto statement didn't generate enough headaches, to cause real pain he came up with multiple inheritance.   The masochists happiest day so far.



(FPC v3.0.4 and Lazarus 1.8.2) or (FPC v3.2.2 and Lazarus v3.2) on Windows 7 SP1 64bit.

 

TinyPortal © 2005-2018