[fpc-pascal] Question about interfaces and patch
Michael Van Canneyt
michael at freepascal.org
Thu Mar 24 21:21:02 CET 2005
On Thu, 24 Mar 2005, ml wrote:
[Cut]
> > >
> > > 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 ?
> >
>
> Yeah, exactly like this. And now the bug of this effect. With this you
> get a whole bunch of calling procedures and functions and all are
> accepting TInterfacedObject parameter. You don't know what actual
> parameter is. With passing interfaces as parameters code is much
> cleaner. And all functions are defined as restrictive what kind of
> interface is accepted.
OK, now I see where you're going.
Your last sentence means: I want DoReport to accept only an 'IReportable'
But at the same time, your code is checking that behind 'IReportable'
there is also an 'ILogged'.
I find this a bit contradictory; If you pass an TInterfacedObject, then
you can check for as much classes or interfaces as you want.
The code remains the same. But this is not a principal question.
More important is: what happens if IReportable is an interface obtained
from Windows ? How can you tell whether an interface comes from a Pascal
class, or was obtained from a Windows OLE or ActiveX server ?
There may not be a a real class behind IReportable.
You can construct IReportable interfaces on the fly.
(OpenOffice does it, and I think some SOAP implementations as well)
> > 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 ?
> >
>
> I see, and I named you reason why. Mostly readability of your code.
>
> > 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 ?
> >
>
> Yes.
>
> > This still does not explain why you would need to do
> >
> > AClassInstance := AnInterface;
> >
>
> The only reason why, is mostly internal (where vmt problems were
> discussed). If "is" and "as" would be solved as I suggested, this isn't
> necessary anymore. Meaning I can test if original object (and not
> interface) implements some other interface and then act as that
> interface, then this is not necessary anymore.
>
> Having ability to do
>
> if (aRep is ILogged) then
> (aRep as ILogged).Log(aRep.Report);
>
> would make clean code, where possible calling parameter is obvious
>
> Second reason why could be treated as internal too.
>
> For now you have to specify properties as
>
> type
> IA = interface
> function GetSome: integer;
> procedure SetSome(aValue: integer);
> property Some: integer read GetSome write SetSome;
> end;
>
> this is needed because interface has no clue of original vmt. while
> blind properties definition would be
>
> type
> IA = interface
> property Some: integer read object write object;
> end;
>
> and the implementation of property is left to class, not conditioned
> with function and procedure
I think the properties are needed, to remain compatible with COM
interfaces, which only have methods, I think CORBA has this restriction
too; They don't have 'properties'.
After all the discussion, I see 2 real improvements:
- To be able to use 'Is' operator on interfaces.
(so without the need for 'Supports')
- Use 'as' on interfaces. (But this should be possible as in Delphi)
As for querying the class behind the interface: first you need to answer the
windows problem.
Michael.
More information about the fpc-pascal
mailing list