[fpc-pascal] Question about interfaces and patch

ml ml at brainwashers.org
Thu Mar 24 13:47:52 CET 2005

On Thu, 2005-03-24 at 09:06 +0100, Michael Van Canneyt wrote:
> On Thu, 24 Mar 2005 ml at brainwashers.org wrote:
> > Quoting Michael Van Canneyt <michael.vancanneyt at wisa.be>:
> >
> >>
> >>
> >> On Wed, 23 Mar 2005 ml at brainwashers.org wrote:
> >>
> >>> Quoting Marco van de Voort <marcov at stack.nl>:
> >>>
> >>>>> On Tue, 22 Mar 2005, ml wrote:
> >>>>>> // than one interface
> >>>>>>  a := (object as IA); // correct
> >>>>>>  b := (object as IB); // returns pointer to the first interface
> >>> vmt=IA
> >>>>>>  c := (object as IC); // returns pointer to the first interface
> >>> vmt=IA
> >>>>>> // there's no way to do again it's like direct call to exception
> >>>>>>  obj := a; // returns pointer(obj) + 12 ???
> >>>>>
> >>>>> This is nonsense. You cannot assign an interface to a class.
> >>>>> A class IMPLEMENTS an interface, it is not an interface.
> >>>
> >>> Ok, its nonsense. I said it already works with my patch, but I guess you
> >>> know it better. So my example down there doesn't work (with patch). You
> >>> should know.
> >>> I (; can't ;) transfer from one interface to other back to object and to
> >>> 3rd interface. I just imagine my results.
> >>
> >> Tell me, what is
> >>
> >>    obj := a;
> >>
> >> supposed to DO ? A class has a set of methods. Some of these methods form
> >> the VMT of an interface. What your code does, is say
> >> "don't use your VMT methods, use these instead' ?
> >
> > Yes, exactly. I even provided test example at the bottom of my previous message,
> > where I transfered from class to IA, back to class and then to ID. And called
> > ID.D; And it just works (this is also nice start for blind properties
> > implementation, which now also became possible, since original vmt is now visible)
> >
> > But, It should be used as
> >
> > if (TObject(a).InheritedFrom(TSomeClass)) then begin
> >  obj := TSomeClass(a); // note that here obj is declared as TSomeClass
> >  // now safely use as this vmt
> > end;
> >
> > if SupportsInterface(TObject(a), IB) then begin
> >  ibvar := a;  // declared ibvar: IB
> >  // now safely use as this vmt
> > end;
> >
> > in perfect world "is" would return InheritedFrom or SupportsInterface result and
> > not actual class check, if true then all needed operations are satisfied.
> I can understand that 'is' should be able to check interfaces; this is a
> useful patch.
> I also understand what your code should do.
> BUT I see some flaws in your design.
>   IA = Interface
>     procedure InitF;
>   end;
>   TA = class(TObject,IA)
>     F : TList;
>     Procedure InitF;
>     Procedure B;
>   end;
>   Procedure TA.InitF;
>   begin
>     F:=Tlist.Create;
>   end;
>   Procedure TA.B;
>   begin
>     F.Add(SomePointer);
>   end;
> Var
>    A : TA;
>    C : IA;
> begin

Completely wrong type of thinking here, and I can't answer you what you
asked, so I provided answer why I can't answer and how it should be used

>    A:=TA.Create;
>    C:=SomeIA;    // Get an IA interface from somewhere.

Why would someone create one object just to override its variable with
some other value? To create memory leaks?

>    A:=C;
>    A.InitF;      // <<--- Which InitF should be used ?
>    A.B;          // Crash or not ?

:? Depends, but your example is one complete mistake of using this. It
makes sense just as my example with pointer down here. So... would it
crash? Yeah, probably just the same as

  p, r: pchar;
  i: integer;
  GetMem(p, 100);
  for i := 0 to 10000000 do
    p[i] := #0;
  GetMem(r, 1000);
  p := r; // I intentionally haven't freed pointer 
          // like you didn't in your example
  // So, how does pascal handle this? It can't.
  // Those who code should know what they do

Question here is different. Was that my mistake as programmer or fpc
mistake for not predicting my stupidity. Guess what, it wasn't fpc
fault, so if some interfaced object doesn't initialize its variables,
and others do. Correct the problem there and don't blame wrong

> end;

If you would at least write

  Procedure TA.B;
>   begin
      if F = nil then
>     F.Add(SomePointer);
>   end;

your example would work

> If TA.InitF is used, then B runs OK, but then A:=C has no meaning at all.
> If the InitF from C is used, then F will not be initialized, and B will
> fail.

Here we go again. Your main problem is that you don't understand (or you
lack imagination) what interface is in his complete feature set. Main
feature of interfaces is to have ability to predict combinations of
commands that interfaces support, as I already specified... having
monolithic interface structure makes no sense (you just get mirror copy
of classes), it's a waste of time, paper and space. And before you
answer how it is not possible, or how you don't have time to implement
it. I'm game. I'm prepared to make all the necessary changes and
patches. All that I would ask for is a few pointers (if that could be
done on line on some irc or msn channel, that would be perfect, it's
hard to talk in one e-mail a day) how and where so that I don't need to
dissect complete compiler code (you probably understand that I'm not as
familiar with its code as you are, that would be only few questions like
"where does it...", "how does it...", "what would be the preffered
implementation of ...").

Here is a simple example how it should be used

  IReportable = interface
    function Report: string; 
    // let's say that this should write report and 
    // return status description as string

  ILogged = interface
    procedure Log(aStr: string);

And now some completely different place in your software, main feature
of interfaces is that you can predict possible features, and not even
start to implement them at that moment

procedure MyXYZPart.DoReport(aRep: IReportable);
  if (aRep <> nil) then begin
    if (aRep is ILogged) then
      (aRep as ILogged).Log(aRep.Report)

Meaning, that if I derived some class as (and call DoReport with it as
  TSomeClass = interface(TInterfacedObject, IReportable, ILogged)

this class will have to contain all the logging facility needed, and
that's conditioned with interfaces (otherwise it won't be compiled).

  TSomeClass2 = interface(TInterfacedObject, IReportable)

this class will automatically skip logging, because logging interface is
not supported by class

What is difference here? I could pass a simple interfaced object as
parameter and predict possibility of logging. If object or interface
support that option then all the facility needed is supported and
logging is done.

This is how and why interfaces should be used, for predicting features.
And with interfaces as they are this is just impossible.

I hope that you start seeing power behind more flexible interfaces

> Michael.
> _______________________________________________
> fpc-pascal maillist  -  fpc-pascal at lists.freepascal.org
> http://lists.freepascal.org/mailman/listinfo/fpc-pascal

More information about the fpc-pascal mailing list