Default Directive
The
default
directive has two uses in property
declarations:
To make an array property the class’s default property
To supply a default value for an ordinal-type property
A class can declare one array property as the default property for
the class. The default property lets you refer to an object reference
as an array without mentioning the property name. For example,
TList
declares the Items
property as its default array property. If List
is
a variable of type TList
, you can refer to a list
element as List[Index]
, which is a shorthand for
List.Items[Index]
. A class can have only one
default property. Derived classes can define a different default
property from that of an ancestor class.
An ordinal-type property (integer, enumeration, set, or character
type) can list a default value. The default value has no effect on
the property’s initial value. Instead, the default value is
stored in the class’s RTTI, and Delphi’s design-time and
runtime environments use the default value to reduce the size of a
.dfm file or resource. Non-ordinal properties
(e.g., floating-point, string, class) always use zero (empty string,
nil
, etc.) as the default value.
If you do not specify a default
directive, Delphi
assumes you mean nodefault
and stores the smallest
integer (-2,147,483,648) as the property’s default value. A
side effect is that you cannot use the smallest integer as a
property’s default value. If you do, Delphi interprets it as
nodefault
.
Because the default directive affects only a class’s RTTI, you must write your constructor to set the default value for each property. You can use RTTI to your advantage by reading the default values from the class’s RTTI and setting the object’s default values accordingly, as shown here:
// Set an object's default values by getting those values from // the class's RTTI. Call this procedure from the constructor // of any class that uses the default directive. procedure SetDefaultValues(Obj: TObject); const tkOrdinal = [tkEnumeration, tkSet, tkInteger, tkChar, tkWChar]; NoDefault = Low(Integer); var Count, I: Integer; PropList: PPropList; begin // Make sure the class has published properties & RTTI. if (Obj <> nil) and (Obj.ClassInfo <> nil) then begin // Get the number of ordinal-type properties Count := GetPropList(Obj.ClassInfo, tkOrdinal, nil); GetMem(PropList, Count * SizeOf(PPropInfo)); try // Get the ordinal-type properties. GetPropList(Obj.ClassInfo, tkOrdinal, PropList); for I := 0 to Count-1 do // For each property, if the property has a default value, // set the property's value to the default. if PropList[I].Default <> NoDefault then SetOrdProp(Obj, PropList[I], PropList[I].Default); finally FreeMem(PropList); end; end; end;