I Delphi, "gränssnitt" har två distinkta betydelser. I OOP jargong, du kan tänka dig ett gränssnitt som en klass utan implementering. I Delphi enhetsdefinitionsgränssnitt används avsnitt för att deklarera alla offentliga kodavsnitt som visas i en enhet. Den här artikeln kommer att förklara gränssnitt från ett OOP-perspektiv.
Om du vill skapa en bunnsolid applikation på ett sätt som din kod är underhållbar, återanvändbar och flexibel OOP naturen i Delphi hjälper dig att köra de första 70% av din rutt. Att definiera gränssnitt och implementera dem hjälper till med de återstående 30%.
Abstrakta klasser
Du kan tänka på ett gränssnitt som en abstrakt klass med all implementering avdragen och allt som inte är offentligt bort. En abstrakt klass i Delphi är en klass som inte kan instanseras - du kan inte skapa ett objekt från en klass markerad som abstrakt.
Låt oss ta en titt på ett exempel på gränssnittsdeklaration:
typ
IConfigChanged = gränssnitt[ '{0D57624C-CDDE-458B-A36C-436AE465B477}']
procedur ApplyConfigChange;
slutet;
De IConfigChanged är ett gränssnitt. Ett gränssnitt definieras ungefär som en klass, nyckelordet "gränssnitt" används istället för "klass". Guidevärdet som följer gränssnittets nyckelord används av kompilatorn för att identifiera gränssnittet på ett unikt sätt. För att generera ett nytt GUID-värde trycker du bara på Ctrl + Shift + G i Delphi IDE. Varje gränssnitt du definierar behöver ett unikt Guid-värde.
Ett gränssnitt i OOP definierar en abstraktion - en mall för en faktisk klass som kommer att implementera gränssnittet - som kommer att implementera de metoder som definieras av gränssnittet. Ett gränssnitt gör egentligen ingenting, det har bara en signatur för interaktion med andra (implementerande) klasser eller gränssnitt.
Implementeringen av metoderna (funktioner, procedurer och egendom Get / Set-metoder) görs i klassen som implementerar gränssnittet. I gränssnittsdefinitionen finns det inga omfattningsavsnitt (privata, offentliga, publicerade etc.) allt är offentligt. En gränssnitttyp kan definiera funktioner, procedurer (som så småningom blir metoder i klassen som implementerar gränssnittet) och egenskaper. När ett gränssnitt definierar en egenskap måste det definiera metoderna för get / set - gränssnitt kan inte definiera variabler.
Som med klasser kan ett gränssnitt ärva från andra gränssnitt.
typ
IConfigChangedMore = gränssnitt(IConfigChanged)
procedur ApplyMoreChanges;
slutet;
Programmering
De flesta Delphi-utvecklare när de tänker på gränssnitt de tänker på COM-programmering. Men gränssnitt är bara en OOP-funktion på språket - de är inte bundna till COM specifikt. Gränssnitt kan definieras och implementeras i en Delphi-applikation utan att beröra COM alls.
Genomförande
För att implementera ett gränssnitt måste du lägga till namnet på gränssnittet i klassuppgiften, som i:
typ
TMainForm = klass(TForm, IConfigChanged)
offentlig
procedur ApplyConfigChange;
slutet;
I ovanstående kod implementerar en Delphi-form med namnet "MainForm" IConfigChanged-gränssnittet.
Varning: När en klass implementerar ett gränssnitt måste den implementera alla dess metoder och egenskaper. Om du misslyckas med / glömma att implementera en metod (till exempel: ApplyConfigChange) kommer ett kompileringstidsfel "E2003 odeklarerad identifierare: 'ApplyConfigChange'" kommer att inträffa.
Varning: om du försöker specificera gränssnittet utan GUID-värdet kommer du att få: "E2086 Typ 'IConfigChanged' är ännu inte helt definierad".
Exempel
Överväg en MDI-applikation där flera formulär kan visas för användaren samtidigt. När användaren ändrar applikationskonfigurationen måste de flesta formulär uppdatera sin visning - visa / dölja några knappar, uppdatera etiketttexter, etc. Du behöver ett enkelt sätt att meddela alla öppna formulär att en ändring i applikationskonfigurationen har hänt. Det perfekta verktyget för jobbet var ett gränssnitt.
Varje form som måste uppdateras när konfigurationsändringarna implementerar IConfigChanged. Eftersom konfigurationsskärmen visas modellt, när den stänger nästa kod säkerställer att alla IConfigChanged implementeringsformulär meddelas och ApplyConfigChange kallas:
procedur DoConfigChange ();
var
cnt: heltal;
icc: IConfigChanged;
Börja
för cnt: = 0 till -1 + skärm. FormCount do
Börja
om Stöd (skärm. Formulär [cnt], IConfigChanged, icc) sedan
icc. ApplyConfigChange;
slutet;
slutet;
Stöd fungera (definierat i Sysutils.pas) anger om ett visst objekt eller gränssnitt stöder ett specificerat gränssnitt. Koden upprepas genom skärmen. Formsamling (av TScreen-objektet) - alla formulär som för närvarande visas i applikationen. Om ett formulär Skärm. Former [cnt] stöder gränssnittet, Supports returnerar gränssnittet för den sista parameterparametern och returnerar true.
Därför, om formuläret implementerar IConfigChanged, kan icc-variabeln användas för att anropa metoderna för gränssnittet som implementerat av formuläret. Observera naturligtvis att varje form kan ha sin egen olika implementering av ApplyConfigChange-förfarandet.
Förfäder
Varje klass du definierar i Delphi måste ha en förfader. TObject är den ultimata förfäderna till alla objekt och komponenter. Ovanstående idé gäller även gränssnitt, IInterface är basklassen för alla gränssnitt. IInterface definierar tre metoder: QueryInterface, _AddRef och _Release.
Detta innebär att vårt IConfigChanged också har de tre metoderna, men vi har inte implementerat dem. Detta beror på att TForm ärver från TComponent som redan implementerar IInterface för dig! När du vill implementera ett gränssnitt i en klass som ärver från TObject, se till att din klass ärver från TInterfacedObject istället. Eftersom TInterfacedObject är ett TObject som implementerar IInterface. Till exempel:
TMyClass = klass(TInterfacedObject, IConfigChanged)
procedur ApplyConfigChange;
slutet;
Sammanfattningsvis är IUnbekända = IInterface. IUnknown är för COM.