A
constructor is a special method that creates and initializes instance objects.
The declaration of a constructor looks like a procedure declaration, but it
begins with the word constructor. Examples:
constructor
Create;
constructor
Create(AOwner: TComponent);
Constructors
must use the default register calling convention. Although the
declaration specifies no return value, a constructor returns a reference to the
object it creates or is called in.
A class
can have more than one constructor, but most have only one. It is conventional
to call the constructor Create.
To create
an object, call the constructor method in a class type. For example,
MyObject
:= TMyClass.Create;
This
allocates storage for the new object on the heap, sets the values of all
ordinal fields to zero, assigns nil to all pointer and class-type
fields, and makes all string fields empty. Other actions specified in the
constructor implementation are performed next; typically, objects are
initialized based on values passed as parameters to the constructor. Finally,
the constructor returns a reference to the newly allocated and initialized
object. The type of the returned value is the same as the class type specified
in the constructor call.
If an
exception is raised during execution of a constructor that was invoked on a
class reference, the Destroy destructor is automatically called to
destroy the unfinished object.
When a
constructor is called using an object reference (rather than a class
reference), it does not create an object. Instead, the constructor operates on
the specified object, executing only the statements in the constructor’s
implementation, and then returns a reference to the object. A constructor is
typically invoked on an object reference in conjunction with the reserved word inherited
to execute an inherited constructor.
Here is
an example of a class type and its constructor.
type
TShape = class(TGraphicControl)
private
FPen: TPen;
FBrush: TBrush;
procedure
PenChanged(Sender: TObject);
procedure
BrushChanged(Sender: TObject);
public
constructor
Create(Owner: TComponent); override;
destructor Destroy; override;
...
end;
constructor
TShape.Create(Owner: TComponent);
begin
inherited Create(Owner); // Initialize inherited parts
Width := 65; // Change inherited properties
Height := 65;
FPen := TPen.Create; // Initialize new fields
FPen.OnChange := PenChanged;
FBrush := TBrush.Create;
FBrush.OnChange := BrushChanged;
end;
The first
action of a constructor is usually to call an inherited constructor to
initialize the object’s inherited fields. The constructor then initializes the
fields introduced in the descendant class. Because a constructor always clears
the storage it allocates for a new object, all fields start with a value of
zero (ordinal types), nil (pointer and class types), empty (string
types), or Unassigned (variants). Hence there is no need to initialize
fields in a constructor’s implementation except to nonzero or nonempty values.
When invoked through a class-type identifier, a constructor declared as virtual is equivalent to a static constructor. When combined with class-reference types, however, virtual constructors allow polymorphic construction of objects, that is, construction of objects whose types aren’t known at compile time. (See Class references.)
Method declarations
and implementations
构造器是用于创建和初始化实例对象的特殊方法。构造器声明和过程声明相似,不同的是构造器的声明是以保留字constructor开始。例如:
constructor
Create;
constructor
Create(AOwner: TComponent);
构造器必需使用缺省的register调用约定。尽管构造器的声明没有指定返回值,但构造器总返回其创建或调用中的对象实例的引用。
一个类可以有多于一个构造器,但大多数类只有一个构造器。习惯上调用构造器Create。
要创建一个对象,应调用类中的构造器方法。例如,
MyObject
:= TMyClass.Create;
这里,在堆中为新的对象分配了存储空间,置所有的序数域为零,赋给所有指针和类类型的域以nil值,并且置所有串类型的域为空。接下来执行构造器中指定的其他行为;典型地是,对象基于作为构造器参数传递的值被初始化。最后,构造器返回一个引用,该引用指向新的分配区域和初始化了的对象。返回值的类型域构造器调用中指定的类类型相同。
调用类引用的构造器时,如果在构造器的执行中引发异常,那么析构器Destroy会被自动调用,以销毁未完成的对象。
当用对象引用(胜于类引用)调用其构造器时,不会创建新的对象实例。这时,构造器作用于指定的对象,仅仅执行构造器实现中的语句,然后返回对象引用。作用于对象引用典型的构造器调用是与保留字inherited联合,执行继承的构造器。
下面是一个类类型及其构造器的例子。
type
TShape = class(TGraphicControl)
private
FPen: TPen;
FBrush: TBrush;
procedure
PenChanged(Sender: TObject);
procedure
BrushChanged(Sender: TObject);
public
constructor
Create(Owner: TComponent); override;
destructor Destroy; override;
...
end;
constructor
TShape.Create(Owner: TComponent);
begin
inherited Create(Owner); //初始化继承得到的部分
Width := 65; // 改变继承得到的的属性
Height := 65;
FPen := TPen.Create; // 初始化新的域
FPen.OnChange := PenChanged;
FBrush := TBrush.Create;
FBrush.OnChange := BrushChanged;
end;
构造器的第一个动作通常是调用继承得到的构造器以初始化继承得到的域。然后初始化在后裔类中引入的域。因为构造器总是清除为新的对象分配的存储空间,因此所有的域将以零值(序数类型)、nil(指针和类类型)、空值(串类型)或Unassigned(变体)等开始。因此,除了非零或非空的值之外,没有必要在构造器的实现中对域进行初始化。
当通过一个类类型标识符调用时,作为虚拟方法(virtual)声明的构造器等价于一个静态的构造器。不过,与类引用类型组合时,虚拟的构造器允许多态对象构造,即对象构造的类型在编译时是未知的(见类引用)。