维基副本镜像

这是 pascal.chat 维基的镜像。编辑、历史记录和登录都在那里。

Object Oriented Programming with Free Pascal and Lazarus/zh CN

English · Español · Français · Italiano · Magyar · Македонски · Русский · 中文(中国) · 中文(台灣) · 日本語

有许多Pascal的优秀教程,但是本教程尝试让初学者走得更远,进入面向对象编程,这是对Turbo-pascal,Delphi和FreePascal/Lazar提供的标准Pascal的扩展。

对象是对标准Pascal record结构的扩展

标准的基于文本的Pascal编程善于创建类似传统Unix应用,做一件事并且做得很好的应用。程序做的“一件事”可能是一个非常复杂的动作,可能给用户提供几个菜单驱动的选项,但是它本质上受限于服从用户在键盘上输入的命令,在终端或打印机上列出它的响应。

为了提供一个图形用户界面(GUI),通常要调用某种形式的面向对象编程方法(经常使用C或它的变种,或Visual Basic,或诸如与或不与Lazarus一起使用的FreePascal的Pascal变种)。

在GUI里,有大量以结构化方式排列的图片,由与各种诸如下面行为关联的一系列工具或部件组成的屏幕代表用户。

预期用户在屏幕上移动鼠标或其它光标/选择工具,选择对应鼠标按钮点击或按键执行的行为。

当处理复杂图形用户界面的系统可以用标准Pascal或大多数任意其它编程语言编写时,那么更容易使用一个面向对象系统,在这样的系统里,屏幕上的每个图形对象可以有以通常结构保存在一起的所有属性,与用法关联的过程和函数。

对象——一个现实世界模拟

设想医院或医生办公室收集的血液样本的模拟。

血液样本

实物样本当然地是一个对象;它有与之关联的许多信息,文档和其它实物对象。

申请表的拷贝放在病人笔记里,提醒医生在合适时间里得到结果。

真实的结果是医生用来辅助诊断的纪录,它的拷贝填写在病人笔记里。

为了参考,确认或进一步的测试,实物样本可能被保留;或者可能被冲下洗涤槽或焚化;将有一个方法来描述这。

每次收集样本时,医生不需要阐明所有的细节和指示;确实,他可能没有样本在实验室里如何处理的知识。各种处理的细节是从以前样本收集和分析继承的——整个顺序有一个通用计划,我们可以把血液样本,它的所有文档,数据和底层方法,当作一个复杂的对象。

在医生的心里,血液样本看作和它的结果是一样的实体;对护士和技术人员来说,样本,试管,标签和存储条件组成一个单一实体。

另外一个例子——汽车

如果你不喜欢血液,同样的推理顺序可以应用到放到车库里维修的卡车。 它可能包括:

编程示例

这个预先占领的现实世界例子足够了!(原文:Enough of this pre-occupation with Real-World examples!)让我们前往主要目的:用FreePascal编程。

让我们考虑用FreePascal/Lazarus创建一个有一些控件的一个简单Form的应用。

调用Lazarus IDE时,程序员面对一个空白的Form设计模版,在其上鼓励他放置各种控件或对象。

注意预置的空白Form已经是一个对象了,有它自己的属性,诸如位置(顶部和右部),大小(高和宽),颜色,添加文本的默认字体等等。


如果放置一个Button控件(TButton类型)在Form上,它将有自己的可以在对象察看窗口查看的一系列属性。

几个属性有与Form的属性类似的名称;这是因为许多属性是从一些通用祖先类继承的,这些祖先类勾画出后代类如何定义和处理属性。

正如属性一样,对象察看器提供了一个称作事件的标签(tab),它可以访问事件处理器,事件处理器是指示应用如何处理诸如鼠标点击按钮(OnClick)或位置、大小或其它属性改变(OnChange)等事件的方法。

Form上Button的图片,与其所有属性和事件处理器方法,在Pascal里应该视为一个单一的实体或对象。

标准Pascal的面向对象扩展

通过定义

对象

扩展Pascal的纪录结构 对象是特殊类型的纪录。纪录包含在对象定义(就像一个常规纪录)里声明的所有域,但是现在过程和函数可以声明,仿佛它们是纪录的部分,并作为指向与对象类型关联的方法的指针持有。

例如,一个对象可以包含一个实数数组,以及计算平均值的一个方法。

pascal
Type
  Average = Object
    NumVal: Integer;
    Values: Array [1..200] of Real;
    Function Mean: Real; { calculates the average value of the array }
  End;

对象可以从”父”对象”继承”域和方法。这意味着可以使用这些域和方法,仿佛它们包含在作为”子”对象声明的对象里。

此外,介绍一个能见性的概念:域,过程和函数可以声明为public,protected或private。默认地,域和方法是public的,可以在当前单元之外输出(exporte)。Protected域和方法仅在从当前祖先对象继承的对象里可见。声明为private的域和方法仅在当前单元可见:它们的范围仅限于当前单元的实现。

类

在FreePascal和Lazarus里不经常使用对象本身;相反,非常广泛地使用类。类以与对象几乎相同的方式来定义,但它是一个指向对象的指针而不是对象本身。从技术上讲,这意味着在程序堆上分配类,而在堆栈上分配对象。

这里有一个典型类声明的简单例子:

pascal
{-----------------------------------------}
{example of Class declaration from the LCL}
{-----------------------------------------}
 TPen = class(TFPCustomPen)
 private
   FColor: TColor;
   FPenHandleCached: boolean;
   FReference: TWSPenReference;
   procedure FreeReference;
   function GetHandle: HPEN;
   function GetReference: TWSPenReference;
   procedure ReferenceNeeded;
   procedure SetHandle(const Value: HPEN);
 protected
   procedure DoAllocateResources; override;
   procedure DoDeAllocateResources; override;
   procedure DoCopyProps(From: TFPCanvasHelper); override;
   procedure SetColor
        (const NewColor: TColor; const NewFPColor: TFPColor); virtual;
   procedure SetFPColor(const AValue: TFPColor); override;
   procedure SetColor(Value: TColor);
   procedure SetMode(Value: TPenMode); override;
   procedure SetStyle(Value: TPenStyle); override;
   procedure SetWidth(value: Integer); override;
 public
   constructor Create; override;
   destructor Destroy; override;
   procedure Assign(Source: TPersistent); override;
   property Handle: HPEN read GetHandle write SetHandle; deprecated;
   property Reference: TWSPenReference read GetReference;
 published
   property Color: TColor read FColor write SetColor default clBlack;
   property Mode default pmCopy;
   property Style default psSolid;
   property Width default 1;
 end;

注意该类是作为另一个父或祖先类(TFPCustomPen)的实例来定义的,它继承了其所有属性和方法。它有一些自己的域,用以下的来分组

方法

方法就像标准的过程或函数,但是可能有一些附加的指示(directives)。

上面定义的一些方法以指示virtual标示;其它的以override指示标示。

没有virtual或override指示的方法是静态方法(Pascal的普通种类)。有virtual或override指示的方法动态方法。

方法的特殊实例是:

属性

属性就像常规Pascal纪录里的普通域,但是它们可以有read和/或write符号。

更多信息

这只是触及了主题的表面。需要更多细节,强烈建议读者阅读FreePascal手册,尤其是第5章(对象)和第6章(类)

--Kirkpatc 11:04, 20 July 2008 (CEST)

--SunshineTech翻译完成于2010年1月3日16:51(中国北京)


Console Mode Pascal


From the Free Pascal wiki, page "Object Oriented Programming with Free Pascal and Lazarus/zh CN", as it stood on 2015-06-19 after a change by FTurtle, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's Licensing page. If you have concerns about this material, message the admin.

版本3,最后由WikiArchive于修改。