Шаг 45.
Вариантные типы. Примеры использования

    На этом шаге мы приведем два примера использования вариантных переменных.

    Приведем примеры использования вариантных переменных.


    Пример 1. Здесь демонстрируется присваивание одной и той же вариантной переменной VariantVar значений различных типов. При сознании формы методом TForm1.FormCreate в качестве исходного для VariantVar устанавливается значение строкового типа. А в обработчике события нажатия на кнопку TForm1.Button1Click поочередно присваиваются значения целого, вещественного, булевского и строкового типов. Обратим внимание на выражение:
    VarType(VariantVar) and varTypeMask

в котором используется стандартная функция VarType и маска varTypeMask. Результатом этого выражения является код типа значения вариантной переменной VariantVar.

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    Label1: TLabel;
    Edit1: TEdit;
    Label2: TLabel;
    Edit2: TEdit;
    Button1: TButton;
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

var
  VariantVar : Variant;

procedure TForm1.FormCreate(Sender: TObject);
begin
  VariantVar:='  Это - строка';
  Edit1.Text:='  String';
  Edit2.Text:=VariantVar;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  S : string;
  I,J: Word;
begin
  j:= VarType(VariantVar);
  I :=  j and varTypeMask;
  case I  of
      varString:  begin
                    {Следующий тип - Integer}
                    VariantVar:=-32767;
                    Edit1.Text:='  Integer';
                    Str (VariantVar:5:0, S);
                    Edit2.Text:= S;
                  end;
      varInteger: begin
                    {Следующий тип - Double}
                    VariantVar:=1.7E300;
                    Edit1.Text:='  Double';
                    Str(VariantVar:16:10, S);
                    Edit2.Text:= S;
                  end;
      varDouble:  begin
                    {Следующий тип  - WordBool}
                    VariantVar:=False;
                    Edit1.Text:='  WordBool';
                    Str(VariantVar:3:0, S);
                    Edit2.Text:= S+'    (то есть False)'
                  end;
      varBoolean: begin
	            {Следующий  тип  -  String}
                    VariantVar:='      Это    - строка';
                    Edit1.Text:='      String';
	            Edit2.Text:=VariantVar;
	          end;
  end;
end;

end.
Текст этого примера можно взять здесь.

    Заметим, что при выводе на экран значения вариантной переменной, имеющей текущий булевский тип, в поле редактирования Edit2 появляется не символьное обозначение булевского значения (False, True), a его числовой эквивалент. То есть, для False выводится константа, равная нулю, а для True - константа, не равная нулю.


Рис.2. Вывод значения переменной логического типа


    Пример 2. Здесь показана возможность прямого использования предопределенного типа TVarData, описывающего структуру вариантных переменных, для выполнения действий, аналогичных приведенных в первом примере. Второй пример будет отличаться от предыдущего только некоторыми операторами в методах TForm1.FormCreate и TForm1.Button1Click, которые примут следующий вид:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    Label1: TLabel;
    Edit1: TEdit;
    Label2: TLabel;
    Edit2: TEdit;
    Button1: TButton;
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

var
  VariantVar : Variant;

procedure TForm1.FormCreate(Sender: TObject);
var
  AString : AnsiString;
begin
  TVarData(VariantVar).VType:=varString;
  AString := '  Это - строка';
  TVarData(VariantVar).VString:=Pointer(AString);
  Edit1.Text:='  String';
  Edit2.Text:=VariantVar;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  S : string;
  AString : AnsiString;
begin
  case TVarData(VariantVar).VType of
      varString:  begin
                    {Следующий тип - Integer}
                    TVarData(VariantVar).VType:=varInteger;
                    TVarData(VariantVar).VInteger:=-32767;
                    Edit1.Text:='  Integer';
                    Str (VariantVar:5:0, S);
                    Edit2.Text:= S;
                  end;
      varInteger: begin
                    {Следующий тип - Double}
                    TVarData(VariantVar).VType:=varDouble;
                    TVarData(VariantVar).VDouble:=1.7E300;
                    Edit1.Text:='  Double';
                    Str(VariantVar:16:10, S);
                    Edit2.Text:= S;
                  end;
      varDouble:  begin
                    {Следующий тип  - WordBool}
                    TVarData(VariantVar).VType:=varBoolean;
                    TVarData(VariantVar).VBoolean:=False;
                    Edit1.Text:='  WordBool';
                    Str(VariantVar:3:0, S);
                    Edit2.Text:= S+'    (то есть False)'
                  end;
      varBoolean: begin
	            {Следующий  тип  -  String}
                    TVarData(VariantVar).VType:=varString;
                    AString:='       Это    - строка';
                    TVarData(VariantVar).VString:=Pointer(AString);
                    Edit1.Text:='      String';
	            Edit2.Text:=VariantVar;
	          end;
  end;
end;

end.
Текст этого примера можно взять здесь.

    Снова обратим внимание на выражение оператора выбора case

    TVarData(VariantVar).VType

которое, в отличие от первого примера, берет код типа значения вариантной переменной VariantVar непосредственно из поля VType записи типа TVarData. Как нетрудно заметить, во втором примере для присваивания вариантной переменной VariantVar значения нового типа в поле VType заносится константа, определяющая тип нового значения, а в поле записи TVarData, соответствующее новому типу, записывается собственно значение. Например, для типа Double эти операторы имеют такой вид:

    TVarData(VariantVar).VType:=varDouble; 
    TVarData(VariantVar).VDouble:=1.7E300;

    Кроме того, отметим также особенность присваивания строкового значения прямо в поле VString. Поскольку это поле в типе TVarData описывается как бестиповый указатель Pointer, то строковую константу приходится сначала записывать в переменную типа AnsiString, который допускает преобразование к типу Pointer:

    TVarData(VariantVar).VType:=varString;
    AString   :=   '     Это    - строка';
    TVarData(VariantVar) .VString:=Pointer(AString);   

    При запуске на выполнение проект второго примера работает также, как и первый.

    Со следующего шага мы начнем рассматривать операции и выражения.




Предыдущий шаг Содержание Следующий шаг