I thought to add a CORBA example.
Here I use a CORBA interface that exposes code that is otherwise hidden from use.
Also shows how CORBA memory management is handled. (not!)
{$mode objfpc}{$interfaces corba}
uses
sysutils; // for supports(), that works for CORBA too.
type
ITest = interface
['ITest']
procedure Show;
end;
TTest = class(TObject, ITest)
strict private
procedure Show;
end;
procedure TTest.Show;
begin
writeln('test');
end;
var
T:TTest;
I:ITest;
begin
T:=TTest.create;
{ note that CORBA is case sensitive! }
{ this fails: Supports(T, 'itest' }
writeln(Supports(T,'ITest'));
I:=T;
{ T.show; will not work }
{ I.show will work }
I.Show;
{ CORBA interfaces are assignment compatible to string, not TGUID }
writeln(string(I));
T.free;
readln;
end.
1. The memory management is handled through T (create, free )
2. The show method is exposed by assignment of the class variable T to the interface variable I
3. Since the interface is not reference counted, there is no memory management involved on the interface
4. CORBA interface names are case sensitive and not TGUIDS, they can be assigned to a string.
5. Supports() works, as works one way - through Tobject.getinterfacestr - is won't work.
6. Although creating to the interface variable I is allowed, that is usually a bug, since you can not call free on the interface variable and even a hardcast will fail. (try it...
)
Let's demo that:
var
T:TTest;
I:ITest;
begin
I:=TTest.create; // works, is a bug when using CORBA style interfaces
I.Show;
//T:= I // because this does not work
//T.free;// so you can not do this
// and we have a leak..
// since this is not allowed T:=TTest(I);
// nor this: (I as TTest).Free;
// nor this TTest(I).Free; // this compiles but crashes.
end.
Just like using COM interfaces properly requires discipline, CORBA is no different and also requires discipline. Never mix up the two paradigms.