ghkweon / dwscript

Automatically exported from code.google.com/p/dwscript
0 stars 0 forks source link

Proper handling of interface inheritance #421

Open GoogleCodeExporter opened 8 years ago

GoogleCodeExporter commented 8 years ago
Look at this sample code:

  IParent=interface
    procedure P1;
  end; 

  IChild=interface(IParent) 
    procedure P2;
  end; 

  TChild=class(IChild)
    procedure P1;
    procedure P2;
  end; 

var 
  i_parent: IParent; 
  i_child: IChild; 
  aChild: TChild; 
begin 
  aChild := TChild.Create;

  i_child := aChild;     // (1) OK 
  i_parent := aChild;   // (2) <<- error incompatible types 
  i_parent := i_child;   // (3) OK 

  i_parent.P1;
  i_child.P1;
  i_child.P2;
end;

Line (2) will be ok ONLY if you IMPLICTLY add IParent interface to list of 
interfaces supported by TChild. Why?! Compiler defenitely knows that IChild 
have IPArent as parent, so compiler already reqs that TChild should implement 
P1! But WHY compiler can not get IParent from TChild? Oxygene can ;) 

Delphi can not too, but Delphi have large COM influence and it spoils whole 
interfaces conception in Delphi a lot. Why DWS should use same behaviour? 
Removing such unlogical thing can be backward compatible and is good to make 
language more clear

Original issue reported on code.google.com by deks...@gmail.com on 18 Jun 2013 at 11:56

GoogleCodeExporter commented 8 years ago
Yes. I m aware "diamond problem" with supporting multiply interfaces that have 
common parent interface. 

But we are talking about simple case! Manual casting do the trick, so maybe 
compiler can do it too?

Original comment by deks...@gmail.com on 19 Jun 2013 at 8:28

GoogleCodeExporter commented 8 years ago
Hmm, that raises a priority issue in the cast resolution.

The issue can be illustrated if you have

   TParent = class (IParent)
      private 
         procedure P1;
   end;
   TChild = class (TParent, IChild)
      procedure P1;
      procedure P2;
   end;

Keep in mind that for TParent and TChild in the above case the P1 are different 
methods, and IParent.P1 maps to TParent.P1, while IChild.P1 will map to 
TChild.P1.

When you try to acquire an IParent from a TChild, under the current resolution 
in DWS and Delphi, you'll get the IParent from the TParent.

How does Oxygene resolve the previous case?

There are other intermediate cases to look at, which means that there has to be 
a distance metric to be found, and that achieving compatibility with Oxygene 
without having access to their source code could be non-trivial.

If for instance you have an IRoot, from which IParent derives and you try to 
acquire an IRoot from a TChild, which should get priority? the TChild's IChild 
or TParent's IParent?
What happens if TParent implements IChild and TChild implements IParent?

Is it documented for Oxygene? (couldn't find it in the wiki)
Before this can be implemented in DWS, the various combinations of precedence 
should be tested/reverse engineered, or code will compile but behave 
differently.

Original comment by zar...@gmail.com on 19 Jun 2013 at 3:31

GoogleCodeExporter commented 8 years ago
Agree) we need some more info and some investigations. 

But yours sample case is not simple at all!  You do inherit class, but did not 
override methods. Then you implement in subclass some subinterface! I m agree 
that we should prepare to all cases, but we should stick to practically useful 
things)

Original comment by deks...@gmail.com on 19 Jun 2013 at 4:05

GoogleCodeExporter commented 8 years ago
Even if not common in final code, the compiler still needs to know what to do 
all the time (even if just to report appropriate errors), also such constructs 
may not be so rare if you consider bugs, or that the compiler often has to deal 
with incorrect code.

Last thing to keep in mind if that it can be difficult to change behaviors 
later on without introducing subtle bugs in user's code.

Original comment by zar...@gmail.com on 20 Jun 2013 at 6:46