Interfaces definiëren en implementeren in Delphi

In Delphi, "interface" heeft twee verschillende betekenissen. In OOP jargon, je kunt een interface beschouwen als een klasse zonder implementatie. In de Delphi-eenheid definitie interface sectie wordt gebruikt om alle openbare secties van code die in een eenheid verschijnen aan te geven. In dit artikel worden interfaces uitgelegd vanuit een OOP-perspectief.

Als u er klaar voor bent om een ​​ijzersterke applicatie te maken op een manier die ervoor zorgt dat uw code onderhoudbaar, herbruikbaar en flexibel is OOP aard van Delphi helpt je de eerste 70% van je route te rijden. Het definiëren en implementeren van interfaces helpt met de resterende 30%.

Abstracte klassen

Je kunt een interface beschouwen als een abstracte klasse met alle implementatie verwijderd en alles wat niet openbaar is verwijderd. Een abstracte klasse in Delphi is een klasse die niet kan worden geïnstantieerd - u kunt geen object maken van een klasse die als abstract is gemarkeerd.

Laten we een voorbeeld van een interfaceverklaring bekijken:

instagram viewer
type
IConfigChanged = koppel['{0D57624C-CDDE-458B-A36C-436AE465B477}']
procedure ApplyConfigChange;
einde;

De IConfigChanged is een interface. Een interface is net als een klasse gedefinieerd, het trefwoord "interface" wordt gebruikt in plaats van "klasse". De Guid-waarde die volgt op het interface-trefwoord wordt door de compiler gebruikt om de interface uniek te identificeren. Om een ​​nieuwe GUID-waarde te genereren, drukt u gewoon op Ctrl + Shift + G in de Delphi IDE. Elke interface die u definieert, heeft een unieke Guid-waarde nodig.

Een interface in OOP definieert een abstractie (een sjabloon voor een werkelijke klasse die de interface implementeert) die de methoden implementeert die door de interface zijn gedefinieerd. Een interface doet eigenlijk niets, het heeft alleen een handtekening voor interactie met andere (implementerende) klassen of interfaces.

De implementatie van de methoden (functies, procedures en eigenschap Get / Set-methoden) gebeurt in de klasse die de interface implementeert. In de interfacedefinitie zijn er geen bereiksecties (privé, openbaar, gepubliceerd, enz.) Alles is openbaar. Een interfacetype kan functies, procedures (die uiteindelijk methoden van de klasse worden die de interface implementeert) en eigenschappen definiëren. Wanneer een interface een eigenschap definieert, moet deze de get / set-methoden definiëren - interfaces kunnen geen variabelen definiëren.

Net als bij klassen kan een interface van andere interfaces erven.

type
IConfigChangedMore = koppel(IConfigChanged)
procedure ApplyMoreChanges;
einde;

Programmeren

De meeste Delphi-ontwikkelaars denken aan COM-programmering wanneer ze aan interfaces denken. Interfaces zijn echter slechts een OOP-functie van de taal - ze zijn niet specifiek aan COM gebonden. Interfaces kunnen worden gedefinieerd en geïmplementeerd in een Delphi-toepassing zonder COM aan te raken.

Implementatie

Om een ​​interface te implementeren, moet u de naam van de interface toevoegen aan de klasse-instructie, zoals in:

type
TMainForm = klasse(TForm, IConfigChanged)
openbaar
procedure ApplyConfigChange;
einde;

In de bovenstaande code implementeert een Delphi-formulier "MainForm" de interface IConfigChanged.

Waarschuwing: wanneer een klasse een interface implementeert, moet deze alle methoden en eigenschappen ervan implementeren. Als u een methode (bijvoorbeeld: ApplyConfigChange) niet implementeert / vergeet, een compilatietijdfout "E2003 Niet-aangegeven ID: 'ApplyConfigChange'" zal voorkomen.
Waarschuwing: als u probeert de interface op te geven zonder de GUID-waarde, ontvangt u: "E2086 Type 'IConfigChanged' is nog niet volledig gedefinieerd".

Voorbeeld

Overweeg een MDI-toepassing waarbij verschillende formulieren tegelijk aan de gebruiker kunnen worden weergegeven. Wanneer de gebruiker de applicatieconfiguratie wijzigt, moeten de meeste formulieren hun weergave bijwerken: sommige knoppen weergeven / verbergen, labelbijschriften bijwerken, enz. U zou een eenvoudige manier nodig hebben om alle open formulieren op de hoogte te brengen dat er een wijziging in de toepassingsconfiguratie is gebeurd. Het ideale hulpmiddel voor de klus was een interface.

Elk formulier dat moet worden bijgewerkt wanneer de configuratiewijzigingen worden uitgevoerd, zal IConfigChanged implementeren. Omdat het configuratiescherm modaal wordt weergegeven, zorgt de volgende code ervoor dat bij het sluiten van de volgende code alle IConfigChanged-implementatieformulieren worden gemeld en ApplyConfigChange wordt genoemd:

procedure DoConfigChange ();
var
cnt: geheel getal;
icc: IConfigChanged;
beginnen
voor cnt: = 0 naar -1 + scherm. FormCount Doen
beginnen
als Ondersteunt (scherm. Formulieren [cnt], IConfigChanged, icc) vervolgens
icc. ApplyConfigChange;
einde;
einde;

De steunen functie (gedefinieerd in Sysutils.pas) geeft aan of een bepaald object of een bepaalde interface een opgegeven interface ondersteunt. De code doorloopt het scherm. Formulierenverzameling (van het TScreen-object) - alle formulieren die momenteel in de toepassing worden weergegeven. Als een formulier Scherm. Formulieren [cnt] ondersteunt de interface, ondersteunt de interface voor de laatste parameterparameter en retourneert true.

Daarom, als het formulier de IConfigChanged implementeert, kan de icc-variabele worden gebruikt om de methoden van de interface aan te roepen zoals geïmplementeerd door het formulier. Merk natuurlijk op dat elke vorm kan hebben zijn eigen verschillende implementatie van de ApplyConfigChange-procedure.

Voorvaders

Elke klasse die u definieert in Delphi moet een voorouder hebben. TObject is de ultieme voorouder van alle objecten en componenten. Het bovenstaande idee is ook van toepassing op interfaces, het IInterface is de basisklasse voor alle interfaces. IInterface definieert 3 methoden: QueryInterface, _AddRef en _Release.

Dit betekent dat onze IConfigChanged ook die 3 methoden heeft, maar die hebben we niet geïmplementeerd. Dit komt omdat TForm erft van TComponent dat het IInterface al voor u implementeert! Wanneer u een interface in een klasse wilt implementeren die overneemt van TObject, moet u ervoor zorgen dat uw klasse in plaats daarvan overneemt van TInterfacedObject. Omdat TInterfacedObject een TObject is dat IInterface implementeert. Bijvoorbeeld:

TMyClass = klasse(TInterfacedObject, IConfigChanged)
procedure ApplyConfigChange;
einde;

Tot slot, IUnknown = IInterface. IUnknown is voor COM.