Lesson 6 · 6 of 20
Interfaces · Pascal
Define Object Pascal interfaces, implement them in unrelated classes and let reference counting free the objects for you.

An interface is a contract: a list of methods with no data and no code. ITax only says there is an Apply(net) function. By convention, its name starts with I.
The TVat (mainland Spain VAT, 21 %) and TIgic (Canary Islands tax, 7 %) classes implement the interface: they name it after the parent class, class(TInterfacedObject, ITax), and write their own Apply. They are not related to each other; all they share is the contract. A class inherits from a single parent but can implement several interfaces.
Quote takes an ITax parameter, so it accepts any object that honours the contract, whatever its class. This is how you write code that does not depend on concrete classes.
`TInterfacedObject` brings reference counting: every interface variable or parameter pointing at the object adds one, and when the count drops back to zero the object frees itself. That is why Quote('Madrid', TVat.Create, 250) needs no Free: the object goes away when the call ends. The tax variable keeps its object alive until tax := nil.
The golden rule: an object handled through an interface is never released with Free, nor kept in a class variable at the same time. If you need Supports or the as operator with interfaces, give them a GUID in square brackets.
Code · main.pas
program main;type ITax = interface function Apply(net: Double): Double; end; TVat = class(TInterfacedObject, ITax) function Apply(net: Double): Double; end; TIgic = class(TInterfacedObject, ITax) function Apply(net: Double): Double; end;function TVat.Apply(net: Double): Double;begin Result := net * 1.21; // mainland Spainend;function TIgic.Apply(net: Double): Double;begin Result := net * 1.07; // Canary Islandsend;procedure Quote(const region: String; tax: ITax; net: Double);begin WriteLn(region:9, ': ', net:7:2, ' net -> ', tax.Apply(net):7:2, ' EUR');end;var tax: ITax;begin Quote('Madrid', TVat.Create, 250); // the object is freed after the call Quote('Tenerife', TIgic.Create, 250); tax := TIgic.Create; // kept alive while tax refers to it Quote('La Palma', tax, 19.99); tax := nil; // last reference gone: freed hereend.Output · fpc main.pas && ./main
Madrid: 250.00 net -> 302.50 EUR Tenerife: 250.00 net -> 267.50 EUR La Palma: 19.99 net -> 21.39 EUR
Key points
- An interface is a list of methods a class promises to provide.
- A class can implement several interfaces.
- An interface parameter accepts any class that implements it.
- With
TInterfacedObject, an object frees itself when no references remain. - Do not mix
Freewith interface-managed objects.
Exercise
Create TExempt = class(TInterfacedObject, ITax) for exports, whose Apply returns the net amount untaxed, and add a Quote('Export', TExempt.Create, 250) line.