Domanda

Vorrei avere alcuni suggerimenti per il seguente problema: supponiamo che tu voglia scrivere adattatori per i controlli VCL. Tutti gli adattatori dovrebbero avere la stessa classe di base, ma differiscono nell'avvolgere i controlli speciali (ad esempio ottenere un valore da un tedit è diverso dall'ottenere un valore da tspinedet). Quindi la prima idea è quella di creare una gerarchia di classe come

TAdapter = class
end;

TEditAdapter = class (TAdapter)
end;

TSpinEditAdapter = class (TAdapter)
end;

Ora voglio introdurre un campo per tenere un riferimento al controllo VCL. Nei miei adattatori speciali voglio - ovviamente - lavorare con la sottoclasse concreta. Ma la classe base dovrebbe contenere anche un riferimento (ad esempio se voglio utilizzare l'adattatore per rendere visibile un controllo).

Possibilità 1 (abbassato nell'accessore di proprietà):

TAdapter = class
protected
  FCtrl : TControl;
end;

TEditAdapter = class (TAdapter)
  public
    property Control : TEdit read GetControl write Setcontrol;
end;
{...}
function TEditAdapter.GetControl : TEdit;
begin
  Result := FCtrl as TEdit;
end;

Quindi, se impledo un metodo specifico, lavoro con il controllo della proprietà, se faccio qualcosa nella mia classe di base utilizzo il campo protetto.

Possibilità 2 (usa una classe base generica):

TAdapter = class
end;

TAdapter <T : TControl> = class (TAdapter)
protected
  FCtrl : T;
end;

TEditAdapter = class (TAdapter <TEdit>)
end;

Quale soluzione preferiresti? O esiste una terza soluzione, che è ancora meglio?

Cordiali saluti,

cristiano

È stato utile?

Soluzione

Non puoi usare i generici per risolvere questo problema, perché ti troverai in una delle due situazioni:

  • La proprietà o il metodo che desideri "adattarsi" (il Text proprietà per esempio) è definita in una classe antenato. In tal caso non hai bisogno di generici perché puoi usare l'unico adattatore per l'antenato e risolvere il problema per tutti i discendenti.
  • La proprietà o il metodo sono introdotti dalla classe che si desidera adattare. In tal caso non è possibile utilizzare generici perché per accedere alla proprietà o al metodo avresti bisogno di un vincolo di tipo generico di quel tipo dato. Esempio. Diciamo che vuoi un adattatore per il Text proprietà di TMyClass. Assumiamo TMyClass è quello che introduce il Text proprietà. Per accedervi, dovresti dichiarare il tipo generico come TGeneric<T:TMyClass> E questo non è in realtà generico.

A mio avviso, la migliore scommessa è scrivere adattatori specifici per ogni classe, come nella tua prima opzione. Potresti essere in grado di utilizzare i trucchi RTTI per semplificare l'implementazione della tua prima opzione, ma non sono sicuro che ne varrebbe la pena.

Altri suggerimenti

La versione generica potrebbe consentire di evitare un codice duplicato, almeno nella classe Tadapter. Usando il T Digita, consentirà un sacco di codice condiviso.

D'altra parte, a causa della gerarchia VCL, le proprietà e i metodi più usati saranno già TControl. Quindi non sono sicuro che ci saranno così tanti codice duplicato nell'implementazione non generica.

Sospetto che la versione non generica produrrà meno codice e RTTI, poiché l'attuale implementazione generica tende a non duplicare la fonte, ma aumentare la dimensione EXE.

IMHO Il design a base generica aggiungerà più astrazione all'implementazione, ma il non generico sarebbe forse più vicino alla gerarchia VCL su cui si adatterà.

Quindi, per il tuo caso particolare (mappatura del VCL), poiché il tuo tentativo è di mappare le classi non generiche, preferirei indagare sulla soluzione non generica.

Per un'altra architettura dell'adattatore (non basata su VCL), probabilmente avrei consigliato una pura implementazione generica, dal basso verso l'alto.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top