How To Use Interfaces
From Lazarus wiki
Jump to navigationJump to search
Copy the text below and it will demonstrate how to use interfaces to write less code, avoid code repetition,..., this is a fully working program.
program interfacesygenerics; {$mode objfpc}{$H+} const STestInterface = '{3FB19775-F5FA-464C-B10C-D8137D742088}'; type ITestInterface = interface [STestInterface] procedure DoSomething; procedure DoItAll; end; { Base class Start } TBaseObject = class(TInterfacedObject) procedure DoAll; end; procedure TBaseObject.DoAll; begin Writeln('TBaseObject DoAll !'); end; { Base class End } type { THook Start} //Interface implementation on a derived class THook = class(TBaseObject, ITestInterface) procedure DoSomething; //Contrary to what is stated on the FPC reference manual //it's now possible to use aliases to indicate //interface implementations procedure ITestInterface.DoItAll = DoAll; end; procedure THook.DoSomething; begin Writeln('THook Doing something !'); end; { THook End} type { TRealClass Start } TRealClass = class(TBaseObject, ITestInterface) private FHook: ITestInterface; public constructor Create; destructor Destroy; override; //Here we tell the compiler that our class //interface implementation is provided by //a member field wich we initialize in this case //on the constructor property Hook: ITestInterface read FHook implements ITestInterface; end; constructor TRealClass.Create; begin //Creating our interface implementor FHook := THook.Create; end; destructor TRealClass.Destroy; begin //Releasing our interface implementor THook(FHook).Free; inherited Destroy; end; { TRealClass End } type //An example of how to use generics to write //general use like procedures //as a bonus they are namespaced by the classname //disadvantage: can't be overloaded generic TFakeClass<_GT> = class class function gmax(a,b: _GT):_GT; end; TFakeClassInt = specialize TFakeClass<integer>; TFakeClassDouble = specialize TFakeClass<double>; class function TFakeClass.gmax(a,b: _GT):_GT; begin if a > b then result := a else result := b; end; var R: TRealClass; I: ITestInterface; begin Writeln('Using regular interfaces'); R := TRealClass.Create; //callign the interfaced function directly R.DoAll; //Calling through the interface if R.GetInterface(STestInterface, I) then begin Writeln('Got interface OK. Calling it'); I.DoSomething; I.DoItAll; end else Writeln('Interface not implemented !'); //using the generated generics function writeln('Integer GMax:', TFakeClassInt.gmax(23,56)); writeln('Double GMax:', TFakeClassDouble.gmax(23.89,56.5)); readln; end.