Delphi - записи с вариантами деталей - PullRequest
6 голосов
/ 26 октября 2011

Я хочу иметь запись (структуру) с «полиморфным» составом.Он будет иметь несколько полей, используемых во всех случаях, и я хочу использовать другие поля только тогда, когда они мне нужны.Я знаю, что могу сделать это с помощью различных частей, объявленных в записях.Я не знаю, возможно ли, что во время разработки я могу получить доступ только к тем элементам, которые мне нужны.Чтобы быть более конкретным, посмотрите на приведенный ниже пример

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.

Возможно ли это?

Ответы [ 3 ]

8 голосов
/ 26 октября 2011

Все вариантные поля в записи варианта доступны всегда, независимо от значения тега.

Чтобы добиться требуемого контроля доступности, вам потребуется использовать свойства и иметь проверки во время выполнения для контроля доступности.

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;
3 голосов
/ 27 октября 2011

Даже если бы я услышал, что по оригинальному определению Паскаля Никлауса Вирта все должно работать так, как вы ожидали, я не видел такого поведения в Delphi, начиная с его предка Turbo Pascal 2.0 . Быстрый просмотр FreePascal показал, что его поведение такое же. Как сказано в документации Delphi :

Вы можете читать или писать в любое поле любого варианта в любое время; но если вы пишете в поле в одном варианте, а затем в поле в другом варианте, возможно, вы перезаписываете свои собственные данные. Тег, если он есть, функционирует как дополнительное поле (типа ordinalType) в не вариантной части записи. "

Что касается ваших намерений, насколько я понял, я бы использовал два разных класса, вроде

    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;

Таким образом, вы можете получить некоторую поддержку от редактора кода IDE даже во время разработки. Более полезным, однако, будет то, что намного будет проще модифицировать и поддерживать позже.

Однако, если вам нужно быстрое переключение значений переменных записи во время выполнения, @ вариант Дэвида Хеффернана , чтобы использовать свойства и иметь проверки во время выполнения, более разумно.

0 голосов
/ 26 октября 2011

Данный пример НЕ является вариантом записи, он включает все поля все время.

Истинная запись варианта имеет варианты, использующие одну и ту же память.Вы просто используете синтаксис case дискриминатор: DiscType of ....., вам не нужно отдельное поле, сообщающее, какой вариант активен.

...