Delphi notează șabloane în Delphi (dar nu generice)

Voi scrie în propriile mele cuvinte, sper într-o formă accesibilă cititorului de masă.

Deci, să presupunem că avem o pereche de clase: TSomeType1 și TSomeType2. care sunt declarate în SomeUnit.pas. Și să presupunem că aceste clase au același set de proprietăți și metode, dar aceste proprietăți și metode nu sunt declarate în strămoșii lor obișnuiți. De exemplu, permiteți-l:







Aici vedem metoda DoSomething. care este în ambele clase. Dar acestea sunt două metode diferite.

SFAT: Să presupunem că nu avem ocazia să facem schimbări în SomeUnit.pas. Acest lucru este important pentru înțelegerea motivului pentru care descriu această abordare.

Și acum să spunem că avem o sarcină. scrie o clasă care va lucra cu exemplele clasei noastre, numindu-le DoSomething (pentru unele evenimente). Și de atunci TSomeType1 și TSomeType2 sunt clase diferite, atunci trebuie să scriem două clase noi. Noi le numim T1 și T2, respectiv. Cum se poate face acest lucru? De exemplu, pe frunte (fișierul MyUnit.pas):

Indicație: Apelul DoSomething apare o singură dată în constructorul clasei T1 și T2. Acest lucru nu este practic deloc, dar acesta este doar un exemplu pe care vreau să demonstrez tehnica descrisă.

Și folosiți-o undeva în codul de genul:

Acum, imaginați-vă că clasele noastre T1 și T2 fac mult mai mult de lucru. Ie codul va fi mai mult. Dar, astfel, codul va coincide. Există o dublare a codului. Cum se poate evita aceasta?

Gândire în primul rând - generalizări

Să încercăm generalizări. ele sunt, de asemenea, generice. MyUnit.pas va arata astfel:

Dar, din păcate, acest cod nu se va compila. Deoarece pentru a compila linia FObject.DoSomething, trebuie să știți că metoda DoSomething este de tip T. și că compilatorul pur și simplu nu poate ști. Și nu am găsit o modalitate de ao defini în nici un fel. Puteți specifica în mod explicit ce clasă ar trebui să moștenească de la tipul T. sau care tip de interfață T ar trebui să accepte. Dar în exemplul nostru acest lucru nu este potrivit (nu putem face modificări în SomeUnit.pas, amintiți?).







Al doilea gând este șabloanele de coduri

Acest cod trebuie înlocuit de două ori. Dar într-un fișier acest lucru nu se poate face, așa că am creat două fișiere auxiliare.

SFAT: Dacă nu înțelegeți foarte bine ce se întâmplă aici, înlocuiți conținutul fișierului X.inc în fișierele A.pas și B.pas în locul directivei. Și veți vedea că au existat două module complete.

SFAT: Strict vorbind, nu am evitat duplicarea codului executabil (ca și în cazul genericelor). Când vom compila exemplul nostru, fișierul inc va fi înlocuit de două ori. Dar am reușit să evităm duplicarea la nivelul codului sursă - iar acest lucru, uneori, merită foarte mult.

Apoi, modulul MyUnit.pas trebuie să fie rescris, acesta va deveni acest lucru:

Și o putem folosi exact așa cum a fost arătat mai sus.

De ce este necesar

În cazul în care nu este posibilă modificarea modulului sursă de tip SomeUnit.pas. o astfel de tehnică poate fi singura care permite rezolvarea unor probleme similare.

De exemplu, în VCL există o componentă TCombobox. În modul Style = csSimple sau Style = csDropdown, funcționează ca un mod normal TEdit. Ambele TCombobox și TEdit au un set de proprietăți similare: MaxLength. SelStart. SelLength. SelText, etc. Dar aceste proprietăți sunt declarate nu în strămoșii lor obișnuiți (TWinControl), ci în clasele TCustomComboBox și TCustomEdit, respectiv.

În articolul precedent, am descris modul în care puteți schimba ușor comportamentul standard al proprietății MaxLength pentru moștenitorii de la TCustomEdit (de ex., TEdit, TMemo, etc.). Și pentru a putea aplica TCustomComboBox - vom folosi tehnica descrisă mai sus.

Delphi notează șabloane în Delphi (dar nu generice)

Pro și contra acestei tehnici

  • Am rezolvat o problemă specială atunci când nu există nici o posibilitate (sau nu există dorință) să se facă schimbări în codul sursă al unei biblioteci terță parte.
  • Am evitat duplicarea codului.
  • Când punem codul într-un fișier inc, avem nevoie de puțin mai multă imaginație decât de obicei: gândiți-vă la nume pentru fișiere și tipuri înlocuibile și imaginați cum va arăta în cele din urmă.
  • IDE, care lucrează cu fișiere inc, nu știe în prealabil ce locații vor fi înlocuite. În consecință, CodeInsight nu funcționează aici. Pot apărea probleme cu refactorizarea și cu formatarea automată a codului.

Și o asemenea nuanță. Debuggerul cu fișiere inc funcționează la fel ca și cu fișierele pas-regulat. Dar (ca și în cazul genericelor) care stabilește un punct de întrerupere în fișierul inc, acest punct este inclus atât pentru T1, cât și pentru T2. Rezolvă prin indicarea condiției punctului de întrerupere, de exemplu: Auto este T1.







Articole similare

Trimiteți-le prietenilor: