初探Object Pascal的类(三)

类的构造函数

Object Pascal中的类有一种特殊的方法叫构造函数

构造函数是一种用来建立实例类的方法。

构造函数用来初始化任何类成员变量,为类分配所必须的内存,或者做任何其他初始化工作。

在上一讲中定义的TVehicle就没有构造函数,若不提供一个构造函数,当建立类时,就会用隐藏的类构造程序(Object Pascal所有类都是从TObject 派生,TObject类有一个构造函数称Create,因此若不提供其他构造函数,一般就调用此构造程序。)虽然对于简单的类来说基本构造程序比较好,但一般总是要为具有一定意义的类提供一个构造函数。构造函数的取名时任意的,但必须用关键字constructor声明,这样就可以把它当做构造函数区别对待了,下面我们继续完善TVehicle类,增加一个构造函数。如下:

type
  TVehicle = class
  private
    CurrentGear: Integer;
    Started: Boolean;
    Speed: Integer;
    procedure StartElectricalSystem;
    procedure StartEngine;
  protected
    procedure StartupProcedure;
  public
    HaveKey: Boolean;
    Start: Boolean;
    procedure SetGear(Gear: Integer);
    procedure Accelerate(Acceleration: Integer);
    procedure Brake(Factor: Integer);
    procedure Turn(Direction: Integer);
    procedure ShutDown;
    constructor Create; { 构造函数}
  end;

特别注意,构造函数是一种特殊类型的方法,它没有返回类型。

类可以有不只一个构造函数,这可有两种不同的方式来实现:

1、 给构造函数以不同的名称,例如:

TVehicle = class
  { 省略其他部分内容} 
  constructor Create;
  constructor CreateModel(Model: string);

2、 通过方法重载声明多重构造函数,构造函数拥有相同的函数名称,但具有不同的参数,例如:

TVehicle = class
  { 省略其他部分内容}
  constructor Create; overload;
  constructor Create(AOwner: TObject); overload; { overload重载}

通常构造函数用Create名称就足够了,重载Create的另一个原因是为了与C++ Builder相兼容。C++不允许构造函数的名称不同,因此必须使用重载来定义多个构造函数。

多重构造函数提供了建立类的不同方法。例如:一个类含有不带参数的构造函数,也可以含有带一个或者多个参数的构造函数,这些参数把字段初始化成一定的值。

再例如假设有一个TMyRect类,它是封装矩形的类。这个类有好几个构造函数,有一个缺省的构造函数,此构造函数用来把所有字段都设置为0,,另外一个用来设置类字段的构造函数。首先我们来看看这种类是如何声明的:

type
  TMyRect = class
  private
    Left: Integer;
    Top: Integer;
    Right: Integer;
    Bottom: Integer;

  public
    function GetWidth: Integer;
    function GetHeight: Integer;
    procedure SetRect(ALeft, ATop, ARight, ABottom: Integer);
    { 两个构造函数}
    constructor Create;  { 此构造函数用来初始化所有字段为0}
    constructor CreateVal(ALeft, ATop, ARight, ABottom: Integer);
    { 此函数用来设置字段为特定值,其中的参数A开头的都是对于构造函数
      来说,都是局部的,,都以A开头,用来区别局部变量和字段的。
      以A开头是一种习惯。
    }
  end;

构造函数的定义如下:

constructor TMyRect.Create;
begin
  inherited Create;
  Left := 0;
  Top := 0;
  Right := 0;
  Bottom := 0;
  { 这里其实没有必要把每个字段初始化为0,
    因为当建立一个类的对象时,所有字段都自动初始化为0
  }
end;

constructor TMyRect.CreateVal(ALeft, ATop, ARight, ABottom: Integer);
begin
  inherited Create;
  Left := ALeft;
  Top := ATop;
  Right := ARight;
  Bottom := ABottom;
end;

Note

当建立一个类的对象时,所有字段都自动初始化为0。

实例化(Instantiation)就是创建被称为实例的类的对象。

如下:

var
  Rect1, Rect2: TMyRect;
begin
  Rect1 := TMyRect.Create;  { 0 * 0 的矩形}
  Rect2 := TMyRect.CreateVal(0, 0, 100, 100); { 100 * 100 大小的矩形}
end.

TMyRect的两个实例都是动态分配内存的,所有的Object Pascal类都是建立在堆上的,所有的类变量因此也是指针。Rect1Rect2变量都是指向TMyRect类的指针。上面的代码意味着内存的消耗,因此在end以前也应该有释放与这两个类实例有关的内存,下一讲中我们将讲到“类的析构函数”。

以上代码均在Delphi7中测试通过。

你可能感兴趣的:(pascal)