[fpc-pascal] Question about interfaces and patch

Michael Van Canneyt michael.vancanneyt at wisa.be
Thu Mar 24 15:01:47 CET 2005



On Thu, 24 Mar 2005, ml wrote:

> 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?

Hey, the

     A:=C;

was supposed to be the equivalent of YOUR code :

   // there's no way to do again it's like direct call to exception
   obj := a; // returns pointer(obj) + 12 ???


?

[...]

> 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 was not going to answer any of this, I'm trying to understand what you
want to accomplish, and why this could be useful for other people.

> 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
>
> type
>  IReportable = interface
>    function Report: string;
>    // let's say that this should write report and
>    // return status description as string
>  end;
>
>  ILogged = interface
>    procedure Log(aStr: string);
>  end;
>
> 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);
> begin
>  if (aRep <> nil) then begin
>    if (aRep is ILogged) then
>      (aRep as ILogged).Log(aRep.Report)
>    else
>      aRep.Report
> end;

I see what you want, but if you would do

procedure MyXYZPart.DoReport(aRep: TInterfacedObject);

begin
   if (aRep <> nil) and arep is IReportable then begin
     if (aRep is ILogged) then
       (aRep as ILogged).Log(aRep.Report)
     else
       aRep.Report
end;

you would have the same effect ?

Necessarily, there is always SOME instance implementing any interface...

>
> Meaning, that if I derived some class as (and call DoReport with it as
> parameter)
> type
>  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.

But with a slight change in your code, I think it is, see above ?

If I understand you correct, you want to query the instance 'behind'
some interface to see if it inmplements another interface, without
having to access the actual instance ?

This still does not explain why you would need to do

   AClassInstance := AnInterface;

( your own obj:=a; statement )
Which seems to me against all pascal rules of strict typing ?

Michael.




More information about the fpc-pascal mailing list