Delphi - записи с вариантными частями

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

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.

Это возможно?


person RBA    schedule 26.10.2011    source источник


Ответы (3)


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

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

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;
person David Heffernan    schedule 26.10.2011
comment
Это совершенно правильно, но в данном случае я бы предпочел использовать класс вместо записи. Это позволит добавить функцию наследования, которая здесь имеет смысл (например, свойство IsEnable обычно обрабатывается на родительском уровне и совместно используется детьми). - person Arnaud Bouchez; 26.10.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 даже во время разработки. Однако более полезным является то, что его будет намного легче изменять и поддерживать позже.

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

person Serhii Kheilyk    schedule 27.10.2011

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

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

person Ancient_Hacker    schedule 26.10.2011
comment
Это вариант записи. Случай так делает. - person David Heffernan; 26.10.2011
comment
Вы говорите об абсолютных переменных, а это совсем другое дело. Дэвид прав, это вариант записи. - person Fabricio Araujo; 27.10.2011
comment
Он не включает все поля, вместо этого он предоставляет доступ ко всем частям после case одновременно, и все они используют одну и ту же память. Таким образом, он похож на абсолютные переменные, за исключением того, что он более структурирован; у вас есть переменная тега; и, возможно, выравнивание памяти немного другое - person Serhii Kheilyk; 27.10.2011