面对对象
在Pascal中,有两种结构数据类型用于实现真实世界对象 :
面向对象的概念
在我们详细介绍之前,让我们定义重要的Pascal与面向对象Pascal相关的术语.
- 对象 : 对象是一种特殊的记录,包含记录等字段;但是,与记录不同,对象包含过程和函数作为对象的一部分.这些过程和函数作为指向与对象类型相关的方法的指针. 
- Class :  Class的定义方式与Object几乎相同,但创建方式有所不同. Class在程序的Heap上分配,而Object在Stack上分配.它是指向对象的指针,而不是对象本身. 
- 实例化类 : 实例化意味着创建该类类型的变量.由于类只是一个指针,因此当声明类类型的变量时,只为指针分配内存,而不是为整个对象分配内存.只有在使用其构造函数对其进行实例化时,才会为该对象分配内存.类的实例也称为"对象",但不要将它们与Object Pascal对象混淆.在本教程中,我们将为Pascal对象编写'Object',为概念对象或类实例编写'object'. 
- 成员变量 : 这些是在Class或Object中定义的变量. 
- 成员函数 : 这些是在类或对象中定义的函数或过程,用于访问对象数据. 
- 成员的可见性 :  ; Object或Class的成员也称为字段.这些领域具有不同的可见性.可见性是指成员的可访问性,即这些成员可以访问的确切位置.对象有三个可见性级别:
 public,
 private
 protected.
 类具有五种可见性类型:
 公共,
 私有,
 严格私有,
 受保护
 已发布.
 
- 继承 : 当通过继承父类的现有功能来定义类时,则认为它是继承的.这里,子类将继承父类的所有或几个成员函数和变量.对象也可以继承. 
- 父类 : 由另一个类继承的类.这也称为基类或超类. 
- 子类 : 从另一个类继承的类.这也称为子类或派生类. 
- 多态性 : 这是一个面向对象的概念,其中相同的功能可用于不同的目的.例如,函数名称将保持不变,但它可能需要不同数量的参数,并且可以执行不同的任务. Pascal类实现多态.对象不实现多态. 
- 重载 : 它是一种多态,其中一些或所有运算符根据其参数的类型具有不同的实现.类似地,函数也可以通过不同的实现来重载. Pascal类实现重载,但Objects不实现. 
- 数据抽象 : 隐藏(抽象)实现细节的任何数据表示. 
- 封装 : 指的是我们将所有数据和成员函数封装在一起形成对象的概念. 
- 构造函数 : 指一种特殊类型的函数,只要有来自类或对象的对象形成就会自动调用. 
- 析构函数 : 指一种特殊类型的函数,只要删除对象或类或超出范围,就会自动调用. 
定义Pascal对象
使用类型声明声明对象.对象声明的一般形式如下 :
type object-identifier = object  
   private
   field1 : field-type;  
   field2 : field-type;  
   ...
   public
   procedure proc1;  
   function f1(): function-type;
   end;  
var objectvar : object-identifier;
让我们定义一个矩形对象,它有两个整数类型数据成员 -  长度和宽度和一些成员函数来操作这些数据成员和一个绘制矩形的过程.
type 
   Rectangle = object  
   private  
      length, width: integer; 
   public  
      constructor init;  
      destructor done;  
      procedure setlength(l: inteter);  
      function getlength(): integer;  
      procedure setwidth(w: integer);  
      function getwidth(): integer;  
      procedure draw;
end;
var
   r1: Rectangle;
   pr1: ^Rectangle;
创建对象后,您将能够调用与该对象相关的成员函数.一个成员函数只能处理相关对象的成员变量.
下面的例子展示了如何设置两个矩形对象的长度和宽度,并通过调用成员函数来绘制它们.
r1.setlength(3);
r1.setwidth(7);
writeln(' Draw a rectangle: ', r1.getlength(), ' by ' , r1.getwidth());
r1.draw;
new(pr1);
pr1^.setlength(5);
pr1^.setwidth(4);
writeln(' Draw a rectangle: ', pr1^.getlength(), ' by ' ,pr1^.getwidth());
pr1^.draw;
dispose(pr1);
以下是一个完整的示例,说明如何在Pascal中使用对象 :
program exObjects;
type 
   Rectangle = object  
   private  
      length, width: integer; 
   public  
      procedure setlength(l: integer);
      function getlength(): integer;  
      procedure setwidth(w: integer);  
      function getwidth(): integer;  
      procedure draw;
end;
var
   r1: Rectangle;
   pr1: ^Rectangle;
procedure Rectangle.setlength(l: integer);
begin
   length := l;
end;
procedure Rectangle.setwidth(w: integer);
begin
   width :=w;
end;
function Rectangle.getlength(): integer;  
begin
   getlength := length;
end;
function Rectangle.getwidth(): integer;  
begin
   getwidth := width;
end;
procedure Rectangle.draw;
var 
   i, j: integer;
begin
   for i:= 1 to length do
   begin
     for j:= 1 to width do
        write(' * ');
     writeln;
   end;
end;
begin
   r1.setlength(3);
   r1.setwidth(7);
   writeln('Draw a rectangle:', r1.getlength(), ' by ' , r1.getwidth());
   r1.draw;
   new(pr1);
   pr1^.setlength(5);
   pr1^.setwidth(4);
   writeln('Draw a rectangle:', pr1^.getlength(), ' by ' ,pr1^.getwidth());
   pr1^.draw;
   dispose(pr1);
end.
编译并执行上述代码时,会产生以下结果 :
Draw a rectangle: 3 by 7
* * * * * * *
* * * * * * *
* * * * * * *
Draw a rectangle: 5 by 4
* * * *
* * * *
* * * *
* * * *
* * * *
对象成员的可见性
可见性表示对象成员的可访问性. Pascal对象成员有三种类型的可见性 :
| Sr.否 | 可见度 | 辅助功能 | 
| 1 | 公开 | 成员可以被程序单位以外的其他单位使用 | 
| 2 | 私人 | 成员只能在当前单位中访问. | 
| 3 | 受保护 | 这些成员仅适用于父对象的后续对象. | 
默认情况下,对象的字段和方法是公共的,并导出到当前单位之外.
Pascal对象的构造函数和析构函数 :
构造函数是特殊类型的方法,每当创建对象时都会自动调用这些方法.只需通过声明一个带有关键字构造函数的方法,就可以在Pascal中创建一个构造函数.
通常,方法名称为Init,但是,您可以提供自己的任何有效标识符.您可以将任意数量的参数传递给构造函数.
析构函数是在销毁对象期间调用的方法.析构函数方法会破坏构造函数创建的任何内存分配.
下面的示例将为Rectangle类提供构造函数和析构函数,该类将在创建对象时初始化矩形的长度和宽度当它超出范围时将其销毁.
program exObjects;
type 
   Rectangle = object  
   private  
      length, width: integer; 
   public  
      constructor init(l, w: integer);
      destructor done;
      procedure setlength(l: integer);
      function getlength(): integer;  
      procedure setwidth(w: integer);  
      function getwidth(): integer;  
      procedure draw;
end;
var
   r1: Rectangle;
   pr1: ^Rectangle;
constructor Rectangle.init(l, w: integer);
begin
   length := l;
   width := w;
end;
destructor Rectangle.done;
begin
   writeln(' Desctructor Called');
end; 
procedure Rectangle.setlength(l: integer);
begin
   length := l;
end;
procedure Rectangle.setwidth(w: integer);
begin
   width :=w;
end;
function Rectangle.getlength(): integer;  
begin
   getlength := length;
end;
function Rectangle.getwidth(): integer;  
begin
   getwidth := width;
end;
procedure Rectangle.draw;
var 
   i, j: integer;
begin
   for i:= 1 to length do
   begin
      for j:= 1 to width do
         write(' * ');
      writeln;
   end;
end;
begin
   r1.init(3, 7);
   writeln('Draw a rectangle:', r1.getlength(), ' by ' , r1.getwidth());
   r1.draw;
   new(pr1, init(5, 4));
   writeln('Draw a rectangle:', pr1^.getlength(), ' by ',pr1^.getwidth());
   pr1^.draw;
   pr1^.init(7, 9);
   writeln('Draw a rectangle:', pr1^.getlength(), ' by ' ,pr1^.getwidth());
   pr1^.draw;
   dispose(pr1);
   r1.done;
end.
编译并执行上述代码时,会产生以下结果 :
Draw a rectangle: 3 by 7
* * * * * * *
* * * * * * *
* * * * * * *
Draw a rectangle: 5 by 4
* * * *
* * * *
* * * *
* * * *
* * * *
Draw a rectangle: 7 by 9
* * * * * * * * *
* * * * * * * * *
* * * * * * * * *
* * * * * * * * *
* * * * * * * * *
* * * * * * * * *
* * * * * * * * *
Destructor Called
Pascal对象的继承
Pascal对象可以选择从父对象继承.以下程序说明了Pascal对象中的继承.让我们创建另一个名为 TableTop 的对象,它继承自Rectangle对象.
program exObjects;
type 
   Rectangle = object  
   private  
      length, width: integer; 
   public  
      procedure setlength(l: integer);  
      function getlength(): integer;  
      procedure setwidth(w: integer);  
      function getwidth(): integer;  
      procedure draw;
end;
TableTop = object (Rectangle)
   private
     material: string;
   public
      function getmaterial(): string;
      procedure setmaterial( m: string);
      procedure displaydetails;
      procedure draw;
end;
var
   tt1: TableTop;
procedure Rectangle.setlength(l: integer);
begin
   length := l;
end;
procedure Rectangle.setwidth(w: integer);
begin
   width :=w;
end;
function Rectangle.getlength(): integer;  
begin
   getlength := length;
end;
function Rectangle.getwidth():integer;
begin
   getwidth := width;
end;
procedure Rectangle.draw;
var 
   i, j: integer;
begin
   for i:= 1 to length do
   begin
      for j:= 1 to width do
         write(' * ');
      writeln;
  end;
end;
function TableTop.getmaterial(): string;
begin
   getmaterial := material;
end;
procedure TableTop.setmaterial( m: string);
begin
   material := m;
end;
procedure TableTop.displaydetails;
begin
   writeln('Table Top: ', self.getlength(), ' by ' , self.getwidth());
   writeln('Material: ', self.getmaterial());
end;
procedure TableTop.draw();
var
   i, j: integer;
begin
   for i:= 1 to length do
   begin
      for j:= 1 to width do
         write(' * ');
   writeln;
   end;
   writeln('Material: ', material);
end;
begin
   tt1.setlength(3);
   tt1.setwidth(7);
   tt1.setmaterial('Wood');
   tt1.displaydetails();
   writeln;
   writeln('Calling the Draw method');
   tt1.draw();
end.
以下是重要的一点,应记下来 :
- 对象 Tabletop 继承了Rectangle对象的所有成员.
TableTop 中也有一个draw方法.当使用 TableTop 对象调用 draw 方法时,会调用TableTop的绘制.
一个名为 self 的隐式实例,它引用了对象的当前实例.
当上面的代码是编译并执行,它产生以下结果 :
Table Top: 3 by 7
Material: Wood
Calling the Draw Method 
* * * * * * *
* * * * * * *
* * * * * * *
Material: Wood