среда, сентября 06, 2006

Advanced Records ("class-like")

Замечательная возможность BDS 2006! Работа с записями превращается в сказку, в смысле элегантности использования при грамотном проектировании. Использование свойств, методов и модификаторов видимости позволяет абстрагироваться от внутренней структуры записи, а применение директивы inline уменьшает/сводит на нет, какие бы то нибыло накладные расходы. В результате получаем работу с абстракцией и имеем при этом "чистый код"! Наличие конструкторов (пусть и параметризированных) облегчает использование advanced records в коде т.к. избавляет от необходимости объявлять переменные. Огромным плюсом является и тот факт, что даже при "конструировании" запись остается статической переменной, что в свою очередь снижает (опять же) накладные расходы и стимулирует к использованию advanced records в качестве перечислителей (enumerators). О перечислителях немного позже ;)

Небольшой пример:

    // Структура для хранения данных о регионе
TData = Record

Public

{$REGION ' Определение вложенных членов '}

Type

// Массив прямоугольников и указатель на него
TRects = Array [0 .. MaxInt Div SizeOf(TRect) - 1] Of TRect;
PRects = ^TRects;

{$ENDREGION}

Strict Private

FBuffer : TByteDynArray;

Function GetPRect(AIndex : Cardinal) : PRect; Inline;

{$REGION ' Методы доступа к значениям свойств '}

Function GetBuffer : Pointer; Inline;
Function GetBufferSize : Integer; Inline;
Function GetHeader : PRgnDataHeader; Inline;
Function GetRects : PRects; Inline;
Function GetRectCount : Integer; Inline;
Procedure SetRectCount(Const Value : Integer); Inline;

{$ENDREGION}

Public

{$REGION ' Поддержка оператора for-in-do '}

Function GetEnumerator : TRectEnumerator; Inline;

{$ENDREGION}

Constructor Create(ARegion : HRGN); Overload;
Constructor Create(ARegion : TRegion); Overload;

Procedure UpdateHeader(ARecalculateBounds : Boolean = False);
Procedure RecalculateBounds;

Function TakeFrom(ARegion : TRegion{$IFDEF LASTERROR_SUPPORT}; Out ALastError : Longword{$ENDIF}) : Boolean; Overload;

{$IFDEF LASTERROR_SUPPORT}

Function TakeFrom(ARegion : TRegion) : Boolean; Overload; Inline;

{$ENDIF}

Function TakeFrom(ARegion : HRGN{$IFDEF LASTERROR_SUPPORT}; Out ALastError : Longword{$ENDIF}) : Boolean; Overload;

{$IFDEF LASTERROR_SUPPORT}

Function TakeFrom(ARegion : HRGN) : Boolean; Overload; Inline;

{$ENDIF}

Function TakeFrom(Const ARects : Array Of TRect) : Boolean; Overload;
Function TakeFrom(Const ABuffer : TByteDynArray) : Boolean; Overload;

Property Buffer : Pointer Read GetBuffer;
Property BufferSize : Integer Read GetBufferSize;
Property Header : PRgnDataHeader Read GetHeader;
Property Rects : PRects Read GetRects;
Property RectCount : Integer Read GetRectCount Write SetRectCount;

End;

Комментариев нет: