Delphi mondială - și com delphi

COM (Component Object Model) - entitate fasole model - una dintre tehnologiile-cheie pe care Windows. Mai mult decât atât, toate noile tehnologii în Windows (Shell, Scripting, suport HTML, etc) pune în aplicare API este un COM-interfețe. Astfel, acum modelul de programare profesională necesită o înțelegere COM și capacitatea ei de a lucra. În acest capitol vom discuta despre conceptele de bază ale COM și în special sprijinul lor în Delphi.

Punctul-cheie, care se bazează pe modelul COM, este noțiunea de interfață. Nu au o înțelegere clară a ceea ce a interfeței, programarea cu succes a COM-obiecte este imposibilă.

Interfață, la figurat vorbind, este „contractul“ între programator și compilator.

Programatorul este de acord să pună în aplicare toate metodele descrise în interfața și urmați cerințele pentru punerea în aplicare a unora dintre ele.

Compilatorul se angajează să creeze în structura internă a programului, care să permită accesul la metodele acestei interfețe, de orice susține același software convenții. Astfel, COM este o tehnologie de limbă independentă și poate fi folosit ca un „lipici“ care leagă programe scrise în diferite limbi.

Interfețele pot fi moștenite. moștenire Interface - o declarație care indică faptul că vechea interfață trebuie să includă toate metodele strămoș.

Astfel, trebuie să înțelegeți următoarele:

  • Interfața nu este o clasă. Clasa poate fi o realizare a interfeței, dar clasa include metode de cod într-un anumit limbaj de programare și de interfață - nr.
  • Interfața este puternic tastat. Atât clientul și realizarea interfeței trebuie să folosească exact aceleași metode și parametri care sunt specificate în descrierea interfeței.
  • Interfața este „același contract.“ Nu puteți defini o nouă versiune a aceeași interfață cu un set de metode modificate (sau parametri), dar cu același identificator.

Acest lucru asigură faptul că noile interfețe nu va fi niciodată în conflict cu cele vechi. Dacă este necesar, extinde funcționalitatea care aveți nevoie pentru a defini o nouă interfață, care este posibil moștenitor vechi, și să pună în aplicare metode suplimentare în ea.

managementul automat al memoriei și de numărare de referință

În plus față de furnizarea independentă a accesului limbaj de programare pentru metodele de obiecte, COM implementează un management automat al memoriei de COM-obiecte. Ea se bazează pe ideea de numărare trimiterile la obiect. Orice client care dorește să utilizeze COM-obiect după crearea sa, trebuie să apeleze în prealabil o metodă predeterminată, care crește numărul de referință intern al obiectului pe unitate. La finalizarea utilizării obiectului client determină alte metode de care reduce valoarea aceluiași contor. În cazul în care contorul ajunge la zero link-COM-obiect se elimină automat din memorie. Acest model permite clienților să nu intru în detalii cu privire la punerea în aplicare a obiectului și a obiectului - servi mai mulți clienți și în mod corespunzător a șterge memoria când ați terminat cu ultima dintre ele.

Pentru a genera un nou valori GUID IDE Delphi servește comenzi rapide Ctrl + Shift + G.

Interfața de bază în modelul COM este IUnknown. Orice interfață moștenește de la IUnknown și este obligat să pună în aplicare metodele declarate în ea. IUnknown System.pas declarat în modulul după cum urmează:

Luați în considerare numirea unor metode IUnknown mai detaliat.

Ultimele două metode sunt folosite pentru a pune în aplicare mecanismul de numărare de referință.

Această funcție este de a crește numărul de referință de pe unitatea de interfață și returnează noua valoare a contorului.

Această funcție este de a reduce numărul de referință de pe unitatea de interfață și returnează noua valoare a contorului. În cazul în care contorul ajunge la zero, acesta trebuie să elibereze memoria ocupată de punerea în aplicare a interfeței.

Prima metodă vă permite să obțineți o referință la o interfață pusă în aplicare de clasă.

Această funcție are ca date de intrare identificatorul de interfață. În cazul în care obiectul solicitat implementează o interfață, funcția:

  1. returnează o referință la acesta în parametrul Ob;
  2. Se obține metoda interfață _AddRef;
  3. returnează 0.

În caz contrar - funcția E_NOINTERFACE returnează un cod de eroare.

În principiu, punerea în aplicare specifică a acestor metode pot fi completate de către orice alt, diferit de funcționalitatea standard, dar interfața nu este compatibil cu modelul COM, deci nu este recomandată în acest caz.

În System.pas modul declarat TInterfacedObject clasa, pune în aplicare IUnknown și metodele sale. Se recomandă să se folosească această clasă pentru a crea propriile lor implementari de interfete.

În plus, suportul de interfață este implementată în clasa de baza TObject. El are o metodă

În cazul în care clasa solicitată implementează o interfață, funcția:

  1. returnează o referință la acesta în parametrul Ob;
  2. Se obține metoda interfață _AddRef;
  3. returnează TRUE.

În caz contrar - funcția returnează FALSE.

Astfel, există posibilitatea de a solicita de la orice clasă de Delphi au dat seama că interfață. Utilizarea mai intensă a acestei funcții este discutată mai jos.

clasa TMyClass implementeaza interfete IMyInterface si IDropTarget. Trebuie să se înțeleagă faptul că punerea în aplicare a clasei nu înseamnă mai multe interfețe de moștenire multiplă și toate moștenire de clasă din interfața. Specificarea interfețelor în descrierea clasei înseamnă doar că această clasă pune în aplicare toate aceste interfețe.

Clasa trebuie să aibă o metodă care se potrivesc exact numele și listele de opțiuni toate metodele de toate interfețele declarate în antet.

Să considerăm un exemplu mai detaliat.

Aici clasa TTEST Itest implementeaza interfata. Luați în considerare utilizarea programelor de interfață.

Din moment ce acest cod pare destul de ciudat, să-l ia în considerare mai detaliat.

În primul rând, declarația de atribuire atunci când este activat pentru tipul de date de interfață este implicit metoda _AddRef. Numărul de trimiteri la interfața este incrementat.

Atenție! În cazul în care o clasă se solicită cel puțin o interfață - nu apelată metoda sa liberă (sau distruge). Clasa va fi eliberată atunci când nu mai este nevoie ultimul link pentru interfețele sale. Dacă sunteți în acest moment distrus instanță a clasei de mână - o memorie accesarea de eroare.

De exemplu, următorul cod va cauza o eroare la momentul ieșirii din funcție:

Dacă doriți să distrugă punerea în aplicare a interfeței imediat, fără a aștepta pentru variabila pentru domeniul de aplicare - trebuie doar să dau o valoare de NIL:

Acordați o atenție deosebită faptul că IUnknown apeluri de metode de interfață Delphi făcut implicit și în mod automat. Deci, nu suna IUnknown metode de tine interfață. Acest lucru poate perturba funcționarea normală a numărării de referință automată și să conducă la memorie nelansate sau la încălcarea de protecție a memoriei atunci când se lucrează cu interfețe. Pentru a evita acest lucru, trebuie doar să ne amintim următoarele.

  1. Când este activat, tipul de obiect la o interfață numită _AddRef metodă.
  2. În cazul în care variabila de ieșire care se referă la interfața pentru domeniul de aplicare, sau atunci când atribuie o valoare diferită este numită metoda _Release.
  3. Odată ce solicită o interfață obiect în viitor, nu ar trebui să elibereze manual obiectul. În general, din acest punct înainte este mai bine să lucreze cu un obiect prin referințe interfață.

În acest exemplu, codul pentru interfața din clasa a generat (de tip verificarea) la momentul compilarii. În cazul în care clasa nu implementează interfața necesară, programul nu se va compila. Cu toate acestea, puteți solicita interfață și de rulare. Pentru aceasta servește ca operator, care solicită QueryInterface, și, în caz de succes, returnează o referință la interfața rezultată. În caz contrar, o excepție este aruncată.

De exemplu, următorul cod este compilat cu succes, dar performanța nu va reuși «interfață nu sunt acceptate»:

Acesta va fi compilat și executat cu succes.

Punerea în aplicare a interfețelor (examinare extinsă)

Luați în considerare aspectele legate de punerea în aplicare a interfețelor în detaliu.

Declarați două interfețe:

Acum, creați o clasă care va pune în aplicare aceste două interfețe:

După cum puteți vedea, clasa nu poate conține doar două metode bip. Prin urmare, Delphi oferă o modalitate de a rezolva conflictele de nume, permițând în mod clar ce metodă de clasă va servi ca punerea în aplicare a metodei de interfață corespunzătoare.

În cazul în care punerea în aplicare a metodelor și TTest2.Beep1 TTest2.Beep2 identice, nu puteți crea două metode diferite, și să declare o clasă, după cum urmează:

La punerea în aplicare clase care acceptă mai multe interfețe și multe metode, poate fi convenabil să delege punerea în aplicare a unora dintre aceste clasa copil. Luați în considerare exemplul unei clase care implementează două interfețe:

Pentru a delega punerea în aplicare a unei interfețe către o altă clasă este o pune în aplicare cuvinte cheie.

Această abordare vă permite să împartă punerea în aplicare a unei clase complexe la câteva simplu, care simplifică programarea și îmbunătățește modularitatea programului.

poate accesa cu exactitate clasa derivată precum și la orice clasă care implementează interfața:

Interfețe și TComponent

Clasa de bază VCL TComponent are un set complet de metode pentru punerea în aplicare a interfeței IUnknown, chiar dacă clasa nu implementează această interfață. Acest lucru permite moștenitorii TComponent să pună în aplicare interfețe fără griji despre punerea în aplicare a IUnknown. Cu toate acestea, metodele și programele de rulare TComponent._AddRef TComponent._Release nu implementează link-uri mecanism de numărare, și, prin urmare, pentru clasele derivate TComponent, implementează interfața nu are nici o memorie de management automat efect. Acest lucru vă permite să interogare interfețele lor, fără să se teamă că obiectul este scos din memorie atunci când ieșiți din variabila pentru domeniul de aplicare. Astfel, următorul cod este absolut corectă și în condiții de siguranță:

Acest cod verifică toate formele din interfața IGetData aplicare de fezabilitate și dacă formularul pune în aplicare această interfață, este metoda lui.

Utilizarea interfețe în cadrul programului

Comportamentul discutat mai sus TComponent vă permite să construiască cu ușurință și fără pierderi de tastare puternice, a componentelor aplicației asociate, precum și metode uniforme de numindu-le, fără a necesita ca componentele au fost moștenite de la un strămoș comun. Este suficient pentru a pune în aplicare interfața componente, și în programul de asteptare pentru a verifica prezența sa.

Ca un exemplu, ia în considerare un MDI-aplicație care are o mulțime de diferite forme și o singură bară de instrumente. Să presupunem că pe această bară de instrumente sunt „Save“ comanda „Load“ și „Delete“, dar fiecare fereastră reacționează la aceste comenzi diferite.

Interfața IToolBarCommands descrie un set de metode care trebuie să fie puse în aplicare forme de sprijin de lucru cu butoanele panoului. Metoda SupportedCommands returnează o listă a formei acceptată a comenzii.

Creați trei forme copil - Form2, Form3 și Form4 - și setați proprietatea lor FormStyle = fsMDIChild.

Form2 este capabil de a efectua toate cele trei echipe:

Form3 poate efectua numai clar comanda:

În cele din urmă, Form4 nici un IToolBarCommands implementează interfața și nu răspunde la nici o comandă.

Pe forma principală a aplicației și a pus ActionList crea trei componente TAction. În plus, vom plasa pe ea TToolBar și atribuiți butoanele corespunzătoare TAction.

Cea mai interesantă ActionList1Update metodă, în care sonda pentru forma activă a echipei și a creat interfața principală formă. Dacă nu există nici o formă activă copil, sau nu are suport pentru interfata IToolBarCommands, toate echipele sunt interzise, ​​în caz contrar - numai formă permisă de comenzi acceptate.

Când este activat, comanda verifică prezența formei copil activ, ea a solicitat interfață IToolBarCommands și apelează metoda corespunzătoare:

Programul de lucru este prezentat în figură.

Același efect poate fi atins prin alte metode (de exemplu, moștenind toate formele copil dintr-un strămoș comun sau schimbul de mesaje cu ei), dar aceste metode au unele dezavantaje semnificative.

Deci, atunci când mesaje pierdem tastarea puternică și forțată să treacă parametrii prin numere întregi, și prin moștenire vizuală ne lega la clasa părinte nu este întotdeauna convenabil. În plus, puteți defini un set de interfețe și să pună în aplicare în fiecare dintre formele de copii numai necesare în cazul tuturor formelor de moștenire va trebui să pună în aplicare toate metodele comune.

Folosind interfețe pentru punerea în aplicare Plug-In

Chiar mai convenabil de a utiliza interfețe pentru punerea în aplicare a modulelor de expansiune de program (plug-in). Ca o regulă, un astfel de modul exportă un număr de metode cunoscute pentru programul principal, care pot fi cauzate de aceasta. În același timp, este adesea necesar să se facă referire la orice funcții apelantului. Ambele sunt ușor de implementat folosind interfețe.

Ca un exemplu, să pună în aplicare un program simplu care foloseste plug-in pentru a descărca date.

Anunțați interfețele de module de expansiune și programul API-ul intern.

Acest modul trebuie să fie utilizat în plug-in, precum și în programul principal și asigură utilizarea lor de interfețe identice.

Plug-in este un DLL, exportarea CreateFilter, returnează o referință la interfața ILoadFilter. Modulul principal trebuie să apeleze mai întâi metoda Init, trecându-l numele de fișier și un link către o interfață API-ul intern, și apoi apel metoda GetNextLine, atâta timp cât nu se întoarce FALSE.

Luați în considerare codul modulului de expansiune:

Metoda Init îndeplinește două sarcini: stochează o referință la API-ul este modulul principal pentru utilizare ulterioară și este încercarea de a deschide fișierul de date. Dacă fișierul este deschis cu succes - a prezentat un pavilion InitSuccess intern.

Metoda GetNextLine citește rândul următor de date și returnează TRUE, dacă a reușit sau FALSE - dacă fișierul este complet. În plus, folosind API, furnizate de modulul principal, metoda informează utilizatorul în timpul încărcării.

În destructor am la zero referire la API-ul modulului principal, distrugând-o și închideți fișierul.

Această funcție creează o instanță a clasei care implementează ILoadFilter de interfață. Link-uri pentru a salva o copie a acesteia nu este necesar, acesta va fi eliberat în mod automat.

Acum DLL rezultat poate fi folosit de programul principal.

Clasa TAPI implementează API-ul, oferă modul avansat. ShowMessage modul funcție afișează mesajele în forma principală a aplicației Bara de stare a lui.

Se prepară TMemo pentru datele de încărcare:

Obținem numele modulului cu un filtru pentru extensia de fișier selectat. Module Descrieri stocate în fișiere plugins.ini secțiunea Filtre în format rânduri:

<расширение> = <имя модуля>, de exemplu:

Acum, încercați să încărcați modulul și pentru a găsi funcția CreateFilter:

Funcția este găsit, să creați instanța de filtru și inițializa-l. Deoarece API-ul intern este, de asemenea, implementat ca o interfață - nu este nevoie de a păstra o trimitere la acesta.

Date de încărcare utilizând Creare filtru:

Înainte de descărcare DLL de memorie trebuie să fie sigur pentru a elibera trimiterea la interfața Plug-In, în caz contrar se va întâmpla la ieșirea funcției și poate cauza violare de acces.

Am descărca DLL și actualizare TMemo:

Astfel, pentru a pune în aplicare plug-in-uri pentru a încărca date dintr-o altă țară decât de text, și în mod constant ușor de a lucra cu ei format.

Avantajele acestei metode sunt deosebit de evidente atunci când punerea în aplicare a modulelor de expansiune complexe care interfata este format din mai multe metode.

Atenție! Deoarece EXE și DLL utilizat de linii lungi, nu uitați să includă modulul utilizează ambele proiecte ShareMem. O altă realizare a liniilor de transmisie soluții este de a utiliza tipul de date WideString. Pentru ei, alocarea de memorie este angajată în OLE, și face acest lucru, indiferent de modulul de la care a fost creat linia.

articole similare