- Pascal 教程
- Pascal - 首页
- Pascal - 概述
- Pascal - 环境设置
- Pascal - 程序结构
- Pascal - 基本语法
- Pascal - 数据类型
- Pascal - 变量类型
- Pascal - 常量
- Pascal - 运算符
- Pascal - 决策
- Pascal - 循环
- Pascal - 函数
- Pascal - 过程
- Pascal - 变量作用域
- Pascal - 字符串
- Pascal - 布尔值
- Pascal - 数组
- Pascal - 指针
- Pascal - 记录
- Pascal - 变体
- Pascal - 集合
- Pascal - 文件处理
- Pascal - 内存
- Pascal - 单元
- Pascal - 日期和时间
- Pascal - 对象
- Pascal - 类
- Pascal 有用资源
- Pascal - 快速指南
- Pascal - 有用资源
- Pascal - 讨论
Pascal - 面向对象
我们可以想象我们的宇宙是由不同的物体组成的,例如太阳、地球、月球等。类似地,我们可以想象我们的汽车是由不同的物体组成的,例如车轮、方向盘、齿轮等。同样,存在面向对象的编程概念,它假设一切都是对象,并使用不同的对象来实现软件。在 Pascal 中,有两种结构化数据类型用于实现现实世界中的对象:
- 对象类型
- 类类型
面向对象的概念
在深入了解之前,让我们定义与面向对象 Pascal 相关的重要的 Pascal 术语。
对象 - 对象是一种特殊的记录,它包含类似于记录的字段;但是,与记录不同,对象包含过程和函数作为对象的一部分。这些过程和函数作为指向与对象类型关联的方法的指针保存。
类 - 类的定义方式几乎与对象相同,但创建方式有所不同。类分配在程序的堆上,而对象分配在栈上。它是指向对象的指针,而不是对象本身。
类的实例化 - 实例化意味着创建该类类型的变量。由于类只是一个指针,因此当声明类类型的变量时,仅为指针分配内存,而不是为整个对象分配内存。只有当它使用其构造函数之一进行实例化时,才会为对象分配内存。类的实例也称为“对象”,但不要将其与 Object Pascal 对象混淆。在本教程中,我们将使用“Object”表示 Pascal 对象,使用“object”表示概念对象或类实例。
成员变量 - 这些是在类或对象内部定义的变量。
成员函数 - 这些是在类或对象内部定义的函数或过程,用于访问对象数据。
成员的可见性 - 对象或类的成员也称为字段。这些字段具有不同的可见性。可见性指的是成员的可访问性,即这些成员在何处可访问。对象具有三个可见性级别:public、private 和 protected。类有五种可见性类型:public、private、strictly private、protected 和 published。我们将详细讨论可见性。
继承 - 当通过继承父类的现有功能来定义类时,则称其为继承。此处子类将继承父类所有或部分成员函数和变量。对象也可以被继承。
父类 - 被另一个类继承的类。这也被称为基类或超类。
子类 - 从另一个类继承的类。这也被称为子类或派生类。
多态性 - 这是面向对象的概念,其中同一个函数可以用于不同的目的。例如,函数名称将保持不变,但它可以接受不同数量的参数,并且可以执行不同的任务。Pascal 类实现多态性。对象不实现多态性。
重载 - 它是多态性的一种类型,其中一些或所有运算符根据其参数的类型具有不同的实现。类似地,函数也可以重载,具有不同的实现。Pascal 类实现重载,但对象不实现。
数据抽象 - 任何表示数据的形式,其中实现细节被隐藏(抽象)。
封装 - 指将所有数据和成员函数封装在一起以形成对象的概念。
构造函数 - 指一种特殊的函数类型,每当从类或对象形成对象时,都会自动调用该函数。
析构函数 - 指一种特殊的函数类型,每当对象或类被删除或超出作用域时,都会自动调用该函数。
定义 Pascal 对象
对象使用类型声明来声明。对象声明的一般形式如下:
type object-identifier = object private field1 : field-type; field2 : field-type; ... public procedure proc1; function f1(): function-type; end; var objectvar : object-identifier;
让我们定义一个矩形对象,它有两个整数类型的数据成员 - length 和 width,以及一些用于操作这些数据成员的成员函数,以及一个用于绘制矩形的过程。
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 对象成员具有三种类型的可见性:
| 序号 | 可见性和可访问性 |
|---|---|
| 1 |
Public 成员可被程序单元之外的其他单元使用 |
| 2 |
Private 成员仅在当前单元中可访问。 |
| 3 | Protected 成员仅对从父对象派生的对象可用。 |
默认情况下,对象的字段和方法是 public 的,并且导出到当前单元之外。
Pascal 对象的构造函数和析构函数:
构造函数是一种特殊的类型的方法,每当创建对象时都会自动调用它。您只需使用关键字 constructor 声明方法即可在 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 的 draw。
有一个名为self的隐式实例,它引用对象的当前实例。
当以上代码编译并执行时,会产生以下结果:
Table Top: 3 by 7 Material: Wood Calling the Draw Method * * * * * * * * * * * * * * * * * * * * * Material: Wood