Програмування в Delphi 6
Add ('2-е число: '# 9 + V2);
Вигляд екрану працюючої програми показано на рис. 10.1. Як бачимо, новий варіант легко справляється з підтримкою комплексних чисел: функція VarComplexCreate створює варіант, що містить комплексне число, а подальша поведінка варіанта -стандартна (він підтримує математичні операції та перетворення до рядкового типу). Однак ця легкість оманлива: вихідний текст модуля VarCmplx, який, власне, і надав варіанту додаткові властивості (за замовчуванням розташовується у файлі Source Rtl Common VarCmplx.pas), містить більше 30000 байт.
На с. 229 показано структуру запису TVarData. Два перших байти цього запису (поле VType) зберігають ознака значення варіанта, інші 14 можуть використовуватися розміщення даних.

Мал. 10.1. Демонстрація комплексних варіантів
Створення варіанта користувача проходить в три етапи.
В результаті перерахованих кроків ви отримуєте повноцінний варіант, збагачений новими властивостями: він може зберігати не лише ті значення, які перераховані в таблиці. 10.2, але й будь-які інші, у тому числі властивості та методи! (У цьому останньому випадку спадкоємцем для виконуваного класу нового варіанта замість TCustomVariantType є TInvokeableVariantType або TPublishableVariantType.)
10.5.1. Розміщення у варіанті нових значень
Для розміщення у варіанті нового (не передбаченого стандартним варіантом) значення потрібно створити відповідний клас і помістити у відповідне поле об'єкт цього класу rvarData. Ось як, наприклад, розміщуються комплексні дані у модулі VarCmplx:
TComplexVarData = packed record
Reserved1, Reserved2, Reserved3: Word;
Такий запис лише зберігає 16-байтну структуру TVarData, розміщуючи в полі VComplex.посилання на об'єкт класу TComplexData. Власне комплексні числа зберігаються на полях досить складного класу:
TComplexData = class(TPersistent) private
FReal, FImaginary: Double;
У цьому вся класі передбачені численні методи, управляючі новими даними. Так, простий виклик VarComplexCreate
призводить до спрацьовування кількох методів, що створюють об'єкт VComplex та наповнюють його поля:
процедура VarComplexCreateInto (var ADest: Variant;
const AComplex: TComplexData);
end; функція VarComplexCreate(const AReal, AImaginary: Double):
(CM. файл Source\Rtl\Common\VarCmplx.pas).
10.5.2. Створення спадкоємця TCustomVariantType
Тип TCustomVariantType або його найближчі Спадкоємці TPublishableVariantType і TInvokeableVariantType Містять методи і
властивості, які в потрібний момент викликають методи та властивості об'єкта VC omplex для здійснення тих чи інших перетворень. У модулі varcmpix оголошується такий клас:
class(TPublishableVariantType, IVarStreamable) protected
функція LeftPromotion(const V: TVarData;
const Operator: TVarOp;
out RequiredVarType: TVarType): Boolean; override;
функція RightPromotion(const V: TVarData;
const Operator: TVarOp;
out RequiredVarType: TVarType): Boolean; override;
функція Getlnstance(const V: TVarData): TObject; override;
procedure Clear(var V: TVarData);
функція IsClear(const V: TVarData): Boolean; override;
procedure Copy(var Dest: TVarData;
const Source: TVarData;
const Indirect: Boolean);
procedure Cast(var Dest:
const Source: TVarData);
procedure CastTo(var Dest: TVarData;
const Source: TVarData;
constAVarType: TVarType);
procedure BinaryOp(var Left: TVarData;
const Right: TVarData;
const Operator: TVarOp); override;
procedure UnaryOp(var Right: TVarData;
const Operator: TVarOp);
функція CompareOp (const Left: TVarData;
const Right: TVarData;
const Operator: Integer): Boolean;
procedure Streamin(var Dest: TVarData;
const Stream: TStream);
procedure StreamOut(const Source: TVarData;
const Stream: TStream);
Зверніть увагу: клас TComplexVariantType – інтерфейсний (див. п. 9.4.1). Крім загальних для варіанта методів, він реалізує також два методи, специфічні для інтерфейсу Ivarstreamabie -Streamin і StreamOut, за допомогою яких значення нового інтерфейсу зберігаються в потоці і зчитуються з нього.
Завдання цього класу - дати однакові команди, здатні інтерпретуватися об'єктом vкомплексу як команди перетворення типу даних, що зберігаються, їх порівняння, реалізації над ними тих чи інших операцій, нарешті, запису їх у потік і читання з нього. Наприклад, метод cast цього класу викликається для перетворення інших типів значень до комплексного типу, метод castTo - для зворотного перетворення, метод BinaryOp реалізує бінарну операцію, a Unarydp - унарну і т.д.
Ще раз наголошу, що основна робота (наприклад, з виконання бінарних операцій) реалізується методами класу TComplex-Data. Клас TCompiexVariantType перекриває абстрактні методи свого батька, підключаючи TComplexData до вирішення тієї чи іншої проблеми.
Оскільки для створення екземпляра нового варіанта необхідний вже готовий екземпляр (об'єкт) класу TCompiexVariantType, він створюється у секції ініціалізації модуля varcmpix і знищується у завершальній секції:
10.5.3. створеннядопоміжних методів
Незважаючи на інтенсивне використання класів TCompiexData та TCompiexVariantType, ці класи в кінцевому рахунку залишаються прихованими від користувача нового варіанту за рахунок набору допоміжних
методів, таких як VarComplexCreate, VarIsComplex, VarAsComplex і т.д.
п., які перетворюють звичайні процедурні виклики у виклики методів та звернення до властивостей відповідних класів.