Delphi en Interfaces |
Interfaces kunnen worden beschouwd als een nuttige uitbreiding op de object georienteerde manier van programmeren. Alhoewel een interface eigenlijk niet veel meer is dan een verzameling (virtual abstract) methoden, biedt het krachtige mogelijkheden om het gedrag van een of meer object-georienteerde klassen te specificeren. Een interface geeft alleen aan welke functionaliteit wordt aangeboden door een klasse die de betreffende interface ondersteunt. Een interface zelf geeft geen implementatie van die functionaliteit. De implementatie van een interface wordt in een klasse gedaan. Een klasse kan meerdere interfaces implementeren. De definitie van een klasse die verschillende interfaces ondersteunt doet enigszins denken aan multiple inheritance. Dit is echter niet het geval omdat er geen sprake is van overerving van de implementatie van verschillende interfaces; alleen de specificaties worden geerfd. Het nut van interfaces wordt duidelijk wanneer bepaalde functionaliteit moet worden ondergebracht in klassen die Interfaces kunnen de eigenschappen van een andere interface overerven. Dit wordt interface inheritance genoemd. Ook hier geldt dat alleen de specificaties worden geerfd, niet de implementatie. Bij het ondersteunen van meerdere interfaces is het mogelijk dat twee verschillende interfaces dezelfde naam voor een functie hebben maar waarbij de signatuur van deze functies anders is. Delphi biedt faciliteiten om hiermee om te gaan door het gebruik van zgn. method resolution clauses.
Op het moment dat zowel interface inheritance als implementatie inheritance nodig is, biedt Delphi de mogelijkheid om delegatie en aggregatie toe te passen. Met name wanneer meerde klassen dezelfde interface ondersteunen en ook de code gedeeld moet worden zijn delegatie en aggregatie elegante manieren om dit te doen. Delegatie houdt in dat een (deel van een) interface wordt geimplementeerd door een sub-object. Dit wordt in Delphi aangegeven met behulp van het implements keyword. Bij aggregatie bevat een object een intern object dat de implementatie van een interface verzorgt. Door het toepassen van delegatie wordt de implementatie van een bepaald interface verborgen voor het object dat de interface exporteert. Aggregatie en delegatie kunnen we op verschillende manieren toepassen. Zo kunnen we tijdens run-time voor een bepaalde implementatie van een interface te kiezen. Tevens kunnen aggregatie en delegatie worden toegepast om te voorkomen dat bij het creeren van een instantie van een object alle bijbehorende gegevens ook direkt worden geladen. Op deze manier worden alleen die gegevens geladen die op dat moment relevant zijn.
Laten we tot slot nog even stilstaan bij COM interfaces. Om interfaces te onderscheiden van elkaar, wordt er gebruik gemaakt van unieke identifiers (GUIDs, 16 byte records). Alle COM interfaces zijn direkt of indirekt afgeleid van IUnknown. De IUnknown interface wordt gebruikt om toegang te verkrijgen tot andere interfaces die door een object zijn geimplementeerd. Daarnaast wordt IUnknown gebruikt om reference counting te implementeren. Delphi biedt een speciale klasse (TInterfacedObject) die de functies van IUnknown implementeert. Hierdoor kunnen we ons focussen op de implementatie van specifieke functionaliteit van een interface zonder ons te hoeven bekommeren om de implementatie van IUnknown.
Mocht iemand naar aanleiding van dit stuk nog vragen, opmerkingen of suggesties hebben, dan hoor ik die het liefst via .