2011-10-26 36 views
6

Voglio avere un record (struttura) con un comportamento 'polimorfo'. Avrà diversi campi usati in tutti i casi, e voglio usare altri campi solo quando ne ho bisogno. So che posso farlo con parti varianti dichiarate nei registri. Non so se sia possibile che in fase di progettazione posso accedere solo agli elementi di cui ho bisogno. Per essere più specifici, guarda l'esempio muggitoDelphi - record con parti varianti

program consapp; 

{$APPTYPE CONSOLE} 

uses 
    ExceptionLog, 
    SysUtils; 

type 
    a = record 
    b : integer; 
    case isEnabled : boolean of 
    true : (c:Integer); 
    false : (d:String[50]); 
    end; 


var test:a; 

begin 
test.b:=1; 
test.isEnabled := False; 
test.c := 3; //because isenabled is false, I want that the c element to be unavailable to the coder, and to access only the d element. 
Writeln(test.c); 
readln; 
end. 

È possibile?

risposta

7

Tutti i campi varianti in un record variante sono accessibili in qualsiasi momento, indipendentemente dal valore del tag.

Per ottenere il controllo dell'accessibilità che si sta cercando, è necessario utilizzare le proprietà e disporre di controlli di runtime per controllare l'accessibilità.

type 
    TMyRecord = record 
    strict private 
    FIsEnabled: Boolean; 
    FInt: Integer; 
    FStr: string; 
    // ... declare the property getters and settings here 
    public 
    property IsEnabled: Boolean read FIsEnabled write FIsEnabled; 
    property Int: Integer read GetInt write SetInt; 
    property Str: string read GetString write SetString; 
    end; 
... 
function TMyRecord.GetInt: Integer; 
begin 
    if IsEnabled then 
    Result := FInt 
    else 
    raise EValueNotAvailable.Create('blah blah'); 
end; 
+2

+1. Ero sicuro all'80% che questa è la risposta ... – RBA

+2

Questo è perfettamente corretto, ma in questo caso preferirei usare una classe invece di un record. Permetterà di aggiungere la caratteristica di ereditarietà, che ha senso qui (ad esempio, la proprietà IsEnable viene tipicamente gestita a livello di un genitore e condivisa tra i bambini). –

-3

L'esempio fornito NON è un record di variante, include tutti i campi tutto il tempo.

Un vero record di variante ha le varianti che condividono la stessa memoria. Basta usare la sintassi "case discriminator: DiscType of .....", non c'è bisogno di un campo separato per dirvi quale variante è attiva.

+0

È un record variante. Il caso lo rende così. –

+0

Stai parlando di ** variabili ** assolute, che è un'altra cosa completamente diversa. David ha ragione, questo è un record variante. –

+0

Non include tutti i campi, ma dà l'accesso a tutte le parti dopo 'caso' _ alla stessa ora_, e tutti condividono la stessa memoria. Quindi è simile a ** absolute ** vars, tranne: è più strutturato; hai variabile tag; e, possibile, l'allineamento della memoria è un po 'diverso –

3

Anche se ho sentito che con la definizione Pascal originale di Niklaus Wirth tutto dovrebbe funzionare come previsto, non ho visto un simile comportamento in Delphi, a partire dal suo antenato, Turbo Pascal 2.0. Un'occhiata rapida a FreePascal ha mostrato che lo its behaviour è lo stesso. Come detto in Delphi documentation:

È possibile leggere o scrivere su qualsiasi campo di qualsiasi variante in qualsiasi momento; ma se scrivi su un campo in una variante e poi su un campo in un'altra variante, potresti sovrascrivere i tuoi dati. Il tag, se ce n'è uno, funziona come un campo aggiuntivo (di tipo ordinalType) nella parte non-variante del record ".

Per quanto riguarda il vostro intento, per quanto ho capito, vorrei utilizzare due diverse classi, tipo di

a = class 
     b : Integer 
    end; 

    aEnabled = class(a) 
     c: Integer 
    end; 

    aDisabled = class(a) 
     d: String //plus this way you can use long strings 
    end; 

in questo modo si può ottenere un po 'di sostegno da editor di codice di IDE anche a designtime. più utile, però, è che sarà molto più facile modificare e sostegno in seguito.

Tuttavia, se è necessario passare rapidamente a record va valori corretti in fase di esecuzione, @David Heffernan's variant, per utilizzare le proprietà e avere i controlli di runtime, è più ragionevole.

Problemi correlati