Călătorește prin tobie


Călătorește pe TObject. Sau cum funcționează.

Călătorește pe TObject. Sau cum funcționează.

Fiecare clasă din Delphi este succesorul TObject. și, prin urmare, posedă toate proprietățile și metodele sale. Acesta este, fără îndoială, un fapt util, dar care sunt metodele și proprietățile sale, care sunt proprietățile sale principale și cum pot fi utilizate? Așa cum vom vedea mai târziu, foarte mult în implementarea TObject are ca scop descrierea modelului obiect Delphi.
Să luăm în considerare descrierea sa mai detaliată.

Metodele imediat vizibile ale clasei și funcționalitatea acestora, după cum știți, nu depind de existența specimenului. Să analizăm fiecare dintre aceste metode mai detaliat.

O dată vreau să fac o rezervă, metodele - constructorii și distrugătorii sunt de fapt operatori, și anume interni, care nu depind de implementarea lor în cod, construcții.

Toate obiectele sunt create prin chemarea constructorului. Constructorul în sine nu trebuie să fie numit Creator, este pur și simplu numele acceptat al acestei metode. Constructorul este de fapt o metodă de clasă. iar în procesul de funcționare se numesc următoarele metode: De fapt, apelul la aceste metode este destul de interesant. TObject Constructorul nu efectuează nici o activitate, cu toate acestea, ca rădăcină a ierarhiei de clasă, este creată la nivelul RTM. Ce se întâmplă? Dupa apelarea constructorului este metoda RTM NewInstance care alocă o regiune de memorie, în concordanță cu valoarea vmtInstanceSize, care este generată în timpul compilării. In cadrul apelului NewInstance un InitInstance apel, care umple metoda de câmp valorile indicate în default modificator, în continuare, codul descris în procedura de corp Create (sau cel care este declarat ca un constructor), apoi se trece la punctul definit la vmtAfterConstruction , care implicit indică metoda AfterConstruction. Toate aceste manipulări permit pentru a simplifica procesul de creare a unei instanțe a unui flexibil în cadrul modelului de obiect Delphi. Astfel, atunci când creați o instanță a unei clase (obiect), puteți "participa" la oricare dintre fazele sale. Semnificația procedurii AfterConstruction este de a dezvălui sfârșitul designului clasei. Ușor de utilizat este că acesta se numește numai pe designer de succes pe care le cunosc destul de profitabile. Până în prezent, numai TCustomForm și TCustomDataModule suprasarcină această metodă în mod specific pentru a îndeplini funcțiile lor specifice, astfel încât ceea ce ne împiedică face la fel? Dar aceasta este deja o chestiune de construire a unei clase.

Ce se întâmplă când apare o situație excepțională în cadrul constructorului? Este important să știți aici că toate elementele clasei sunt deja create și când apare o excepție, știm ce puteți șterge. Deci, atunci când se produce o excepție, toate acțiunile asociate distrugerii sunt numite - apelând destructorul, toate în întregime.

Este important să știm că atunci când apelați un constructor de clasă, el este numit ca constructor și creează o instanță atunci când îl numiți constructorul unui obiect, se numește ca procedură și nu creează o instanță nouă, de aici rezultă erorile de tipul următor:

Când apelați metoda constructorului pentru un obiect, este important să rețineți faptul că dacă câmpurile de obiecte sunt create în designer, atunci există un potențial pericol de scurgere de memorie, deoarece sunt create noi instanțe și cele vechi nu sunt distruse.

Această procedură inițiază procesul de distrugere a obiectului în memorie. De ce nu distrugătorul? Apelarea destructorului este eliberarea corectă a resurselor pentru metoda depășită de definire a obiectelor obiect. Dacă te uiți la modul în care funcționează această procedură, poți vedea cea mai interesantă imagine.

Ce vedem? În prima linie, pointerul spre Sine (însuși) este comparat cu zero - și nu am fost deja eliberați? Dacă nu, atunci, în funcție de pointer la vmtDestroy, numim adevăratul distrugător. În caz contrar, procedura se încheie. Astfel, există o verificare trivială pentru un nebun de către RTM Delphi. Când numim distrugătorul, eliberăm imediat (sau nu eliberăm, dar în zadar) resursele obiectului. Din nou, atunci când resursele sunt eliberate, se efectuează un set complet de acțiuni. Metoda FreeInstance numește o cascadă de proceduri pentru a elibera toate resursele capturate, inclusiv agendele dinamice, tipurile de variante și multe altele. Acest lucru ar trebui să fie util atunci când apar situații excepționale în constructor când structurile dinamice interne sunt deja create. Acest lucru este, de asemenea, foarte util ca un mecanism de colectare a gunoiului în interiorul instalației.

funcția de clasă InitInstance (instanță: Pointer): TObject;

Funcția de inițializare a instanței cu informații din VMT, ținând seama de utilizarea interfețelor la moștenire. Este important să se acorde atenție faptului că aceasta este o funcție a clasei, de fapt această funcție umple discul obiect creat de funcția NewInstance.

Procedura de returnare a unei instanțe la conținutul "virgin". Aceasta folosește informațiile stocate în vmtInitTable și vmtParent.

Tipul funcției: TClass;

Returnează clasa de obiecte. Și pentru a fi mai precis, indicatorul VMT este returnat direct.

clasă funcția ClassName: ShortString;

Returnează numele clasei. Se utilizează VMT.

funcția de clasă ClassNameIs (const Nume: șir): Boolean;

Efectuează o reconciliere a numelui cu numele clasei cerute. Se folosește la executarea instrucțiunii is.

clasă funcția ClassParent: TClass;

Returnează un indicator la clasa parentală. Se folosește la executarea instrucțiunii is.

funcție de clasă ClassInfo: Pointer;

Returnează pointerul la informații RTTI despre clasă. Dacă clasa este compilată fără a utiliza directiva $ M +, atunci se returnează zero.

funcția de clasă InstanceSize: Longint;

Dimensiunea instanței. Așa cum se poate vedea din descriere, informațiile despre mărime și RTTI sunt stocate în VMT în afara legării la o anumită instanță. Se pare că aceste informații se formează la momentul compilării.

funcția de clasă InheritsFrom (AClass: TClass): Boolean;

Returnează indicația exactă că această clasă este moștenită de cea pe care o cauți. Această funcție scanează VMT și părinții acestui VMT pentru a se conforma clasei specificate.

funcția de clasă MetodaAddress (const Nume: ShortString): Pointer;

funcția de clasă MethodName (Adresa: Pointer): ShortString;

Funcția este inversă față de cea anterioară.

Funcție FieldAddress (const Nume: ShortString): Pointer;

Accesul la câmpuri. Returnează un câmp în câmp. Ca întotdeauna utilizează VMT.

Funcția GetInterface (const IID: TGUID; Out Obj): Boolean;

Se folosește la moștenirea interfețelor și returnează interfața IID specificată.

funcția de clasă GetInterfaceEntry (const IID: TGUID): PinterfaceEntry;

Returnează punctul de intrare al interfeței la IID specificat.

funcție de clasă GetInterfaceTable: PInterfaceTable;

Tabela de interfață. În ciuda faptului că este revendicată utilizarea unui număr infinit de interfețe, 10.000 de elemente din tabela de interfață sunt indicate clar în textul sursă. Desigur, nu vreau să pun un experiment și să încerc să depășesc această limită, dar progresul se desfășoară într-o asemenea rată care, mă tem, după un timp această limită va fi epuizată.

Funcția SafeCallException (ExceptObject: TObject; ExceptAddr: Pointer): HResult; virtuale;

Procedura după construcție; virtuale;

Procedură înainte de distrugere; virtuale;

Procedura provocată înainte de distrugerea obiectului.

Dispecerizarea procedurilor (mesajul var); virtuale;

Datorită utilizării Windows ca platformă de bază, dezvoltatorii au decis să nu treacă de la modul principal de procesare a interacțiunii interobiect - sistemul de mesaje. Această metodă este realizată doar prin această metodă. A fost foarte rezonabil să o plasăm exact în TObject, deoarece este baza pentru toate clasele definite în modelul obiect Delphi. Această metodă scanează VMT pentru prezența unui handler de mesaje al cărui ID este specificat în primii 4 octeți (cuvânt lung, Cardinal) al parametrului Message și dacă nu găsește că îl primește DefaultHandler. Adică puteți să prindeți evenimente care apar nu numai în cadrul controalelor, ci și în clasele de ierarhie inferioară.

Procedură DefaultHandler (mesaj var); virtuale;

Traductorul evenimentului implicit. Chemată prin metoda Dispeceră când nu se găsește metoda de manipulare a mesajului corespunzător.

funcția de clasă NewInstance: TObject; virtuale;

Creează o instanță a clasei. Este rezonabil să folosiți această funcție pentru a clona obiecte, deoarece fără a cunoaște clasa sursă, puteți crea noi instanțe de obiecte deja terminate fără a utiliza RTTI.

procedura FreeInstance; virtuale;

Eliberă resursele instanței. Utilizarea acestei metode nu este binevenită datorită relației ei apropiate cu VMT, adică suprasolicitarea acestei metode ar trebui făcută cu mare grijă. Apelarea aceleiași metode direct în legătură cu InitInstance poate servi la crearea unei instanțe "în sine", deoarece unele sarcini necesită revenirea statului obiect în momentul creării.

destructor Destroy; virtuale;

De fapt, destructor. Numit de liberă după asigurându-vă că instanța deoarece există. Există un punct cu privire la numirea unui destructor - ar trebui să fie numit Destroy, acest lucru se datorează virtualitate sale, și, astfel, suprasarcina. Dacă numiți distrugătorul cu un nume diferit, atunci când încercați să apelați metoda RTM moștenită, acesta nu va găsi o descriere a metodei cu numele dvs., ceea ce va duce la încălcarea funcționalității procedurii de distrugere a obiectului. Cu toate acestea, este interesant de observat un detaliu. Disponibilitatea de asteptare destructor moștenită nu este necesară, deși de dorit - pentru că nu toți dezvoltatorii să se ocupe de evenimente cum ar fi timpul de execuție, și eliberarea de memorie alocată, de exemplu, se întâmplă fără participarea codului descris în destructor.

Ca urmare a studierii codului sursă, cel mai interesant moment a fost descoperit - când numiți orice metodă în EAX, există un pointer ... la VMT! Nu este o indicație explicită a orientării obiectului Delphi. Studiind materialele cărții "Delphi în coajă de nucă" Ray Lischner (Ray Lischner), am dat peste un fapt interesant - un tabel care compară modele de obiecte ale unor limbi, îmi voi permite să-l aduc cu unele traduceri și adăugiri:

Caracteristicile acceptate ale modelelor obiect ale unor limbi de programare.

Articole similare