第 8章 面向对象程序基础
结构化程序设计是基于求解过程来组织程序流程,在
这种程序中,数据和施加于数据上的操作是分别设计
的,以对数据进行操作的过程作为程序的主体。而面
向对象的程序设计则以对象作为程序的主体。对象是
数据和施加在数据上的操作的封装体。封装在对象中
的程序通过, 消息, 来驱动运行。在图形用户界面中,
消息经常通过鼠标和键盘的某种操作来产生和传递。
本章介绍面向对象程序设计的一些基本概念:如对象、
类、子类、继承、属性、方法、事件等等
? 8.1 面向对象的概念
? 8.2 VFP 对面向对象方法的支持
? 8.3 面向对象的程序设计方法
8.1 面向对象的概念
? 8.1.1 对象与类
? 在面向对象程序设计中,对象( Object)
是组成程序的基本构件
? 在这种方法中,设计人员直接用一种称
之为, 对象, 的程序构件来描述客观问
题中, 实体,,并用, 对象, 间的消息
来模拟实体间的联系,用, 类, 来模拟
这些实体间的共性。
1,对象( Object)
? 在 OOP方法中,作为程序基本构件的
,对象, 是对现实世界中实体的一种模
拟工具
? OOP方法用一组称为, 属性, 的数据模
拟所描述实体的静态特征、而用一组称
为, 方法程序, 的程序过程模拟该实体
对一些, 事件, 的反映
? 把模拟一个实体的, 属性, 数据和, 方
法程序, 通过一定的形式进行, 封装,
就建立起了一个 OOP方法中的对象
2、类( Class)
? ―类, 是具有相同属性特征和行为规则的
多个, 对象, 的一种统一描述
?, 类, 是对现实世界的一种高度抽象与
概括,而, 对象, 则是, 类, 的一个实

?, 对象, 一定具有其属, 类, 的共同特
征与行为规则,当然一个, 对象, 还可
以具有其属, 类, 未曾规定的特征属性
和行为规则
3,事件与响应
? ―事件, 是由外部实体作用在, 对象, 上的一
个动作
? 在 OOP方法中,作用在, 对象, 上的事件包括
对象的创建、释放、收到其他对象发来的, 消
息, 等
? 对于一些可视对象,如命令按钮等,其最常见
的, 事件, 往往是一些鼠标动作,如, 单击,,
,双击,,, 拖放, 或修改对象数据等
? 当作用在对象上的某个设定, 事件, 发生时,
与该事件相联系的, 方法程序, 就运行并完
成该程序的功能
4,事件代码与方法代码
? 事件代码与方法代码都是定义在某个对象中的
一个程序过程,有时也把两者统称为方法代码。
但狭义地说:事件代码可以由一个, 事件, 触
发运行,其过程名与事件名相同,而一般方法
程序没有一个与之对应的事件触发,必须靠其
他程序调用才能得以运行
? 不能为对象建立新的事件,所以一个对象包含
的事件代码的数量是一定的,不能增加
8.1.2子类与继承
? OOP方法中,用, 子类, 来模拟现实世界中的
类的层次问题
?, 子类, 将继承其, 父类, 的全部特征和方法
程序,当然,在, 子类, 中可以对这些继承的
特征和方法程序进行修改以对该, 子类, 进行
更准确的模拟
? 当对, 父类, 进行修改后,这种修改会立即反
映到所有以该, 父类, 为基础而建立的全部
,子类, 中,不管这些, 子类, 是在, 父类,
修改前还是修改后建立的
8.2 VFP 对面向对象方法的支持
? 8.2,1 Visual FoxPro 7.0 的类
?
8.2.2 容器与控件
? Visual FoxPro 7.0的基类共分成两个大类:
容器类和非容器类。一般称容器类基类
为 容器,而把非容器类基类称为 控件,
有时候也把所有基类都称为控件
1.容器类
? 容器类可以包含其他对象,并且允许访问这些
对象。例如,若创建一个含有两个列表框和两
个命令按钮的容器类,而后将该类的一个对象
加入表单中,那么无论在设计时刻还是在运行
时刻,都可以对该容器中任何一个对象进行单
独操作。不仅可以改变列表框的位置和命令按
钮的标题,也可以在设计阶段给这个容器添加
新对象。例如,可以给列表框加标签,来标明
该列表框
2,控件类
? 控件类的封装比容器类更为严密,但也
因此丧失了一些灵活性。控件类没有
AddObject 方法程序。在该, 类, 中不能
包含其他类,最典型的控件类就是命令
按钮。容器类虽然在引用时可以视为一
个整体,但无论是在设计阶段还是在运
行阶段,其所包含的对象都是可以识别
并可以单独操作的
3,容器中各对象的调用
? 容器类中对象的层次
? 容器中的对象仍然可以是一个容器,一般把一个, 对
象, 的直接容器称为, 父容器,,在调用特定的对象
时,搞清该对象的, 父容器, 是至关重要的,不能把
一个对象的间接容器错误地视为其, 父容器, 。
? 对象使用局域名
? 每个对象都有一个名字。在给对象命名时,只要保证
同一个, 父容器, 下的各对象不重名即可,换句话说,
对象使用的是局域名,因此不能单独使用对象名来调
用对象
? 几个代词的用法
? 在进行对象调用时,有几个经常使用的代词,
? This——表示对象本身
? Parent——表示对象的, 父容器, 对象
? ThisForm——表示对象所在的表单
? ThisFormSet——表示对象所在的表单所属的表
单集
?
? 下面是命令组中的按钮对象 Command2中
对应单击鼠标事件 ( Click) 的方法程序,
? This.Parent.command1.Enabled=not
This.Parent.command1.Enabled
? This.Parent.Parent.command1.Enabled=not
This.Parent.command1.Enabled
8.2.3 事件与方法
? 1,OOP方法中的事件
? 如前所述,在 OOP方法中,,事件, 是
驱动蕴涵在对象中的程序的的引擎,一
个事件有一个事件名,一个事件与一个
事件响应程序(方法程序)相关联,当
作用在一个对象上的事件发生时,与这
个事件相关联的程序就获得一次运行
2,OOP方法中对象对事件的反映
? 当作用在对象上的一个事件发生时,系
统就自动执行与该事件关联的代码段,
若没有与之相关联的代码,则不会发生
任何操作
? 表单中所有对象的 Init 事件将在表单的
Init 事件之前执行,所以在表单显示以前,
就可在表单的 Init 事件代码中处理表单
上的任意一个对象
3,方法程序的层次
? ( 1) 容器事件和对象事件
? 为对象编写事件代码时, 应注意以下两
条基本规则,
? ① 容器不处理与所包含的对象相关联的
事件 。
? ② 若没有与某对象相关联的事件代码,
则 Visual FoxPro 在该对象所在类的层次
结构中逐层向上检查是否有与此事件相
关联的代码
? ( 2) 对象方法的继承层次
? 若某个对象基于一个用户子类,当一个
事件在该对象上发生时,Visual FoxPro
首先在该对象中查看是否有与此事件相
关联的代码。若找到,则执行它;否则,
Visual FoxPro 将在类层次中向上逐层检
查。无论 Visual FoxPro 在类层次的哪个
地方找到该事件代码,都执行它,而该
层以上的代码将不会被执行
8.3 面向对象的程序设计方法
? 3.3.1类的设计
? 1.用程序方法设计类
DEFINE CLASS ClassName1 AS ParentClass [OLEPUBLIC]
[[PROTECTED | HIDDEN PropertyName1,PropertyName2,..]
[Object.]PropertyName = eExpression,..]
[ADD OBJECT [PROTECTED] ObjectName AS ClassName2
[NOINIT]
[WITH cPropertylist]]..,
[[PROTECTED | HIDDEN] FUNCTION | PROCEDURE
Name[_ACCESS | _ASSIGN]
[NODEFAULT]
cStatements
[ENDFUNC | ENDPROC]]..,
ENDDEFINE
【 例 8-2】 建立包含一个文本框的表
单子类 test
DEFINE CLASS test AS FORM && 定义 Form 类的一个子类 Test
ADD OBJECT text1 AS TEXTBOX && 为 Test加入一个文本框对象 Text1
PROCEDURE text1.KeyPress
PARAMETERS nKeyCode,nShiftAltCtrl
NODEFAULT
IF BETWEEN(nKeyCode,65,122) && 在 'A' 和 'z' 之间
This.Value = ALLTRIM(This.Value) + "*"
ACTIVATE SCREEN && 将输出发送到 Visual FoxPro 主窗口中
CHR(nKeyCode)
ENDIF
ENDPROC
PROCEDURE Destroy
CLEAR EVENTS
ENDPROC
ENDDEFINE
2,用可视法方法设计类
? 进入 Visual FoxPro所提供的类设计器
? 指定子类的名称和存储类的文件名
?属性设计
选择要设置属性的类类
在这里设置属性值
在这里选择属性
属性选项卡, 下面只出现与
选项相关的属性
属性意义说明
? 代码设计
? 在类上单击鼠标辅按扭,在弹出窗口选择, 代码,
? 双击类的图形
在代码设计窗口有两个下拉列表框,
? 提示为, 对象, 的列表框中可以下拉出该类所包含的
全部对象 ( 对于控件类, 就只有唯一一个对象 ) 。 通
过这个框可以指定为哪个对象设计代码 。
? 提示为, 过程, 的列表框可以下拉出要设计代码的类
所能识别的全部事件及方法代码名称, 通过这个框指
定为哪个事件或方法设计代码 。
8.3.2对象的设计
? 1,创建与释放对象
? 对象的创建
– <对象名 >=CreateObject(―类名, )
? 对象变量的分类
– 全局变量
– 局部变量
– 私有变量
? 对象变量的释放
– Release <对象名 >
? 2.对象的属性设置
– <对象名,属性名 >=<属性值 >
– 或,
WITH <对象名 >
属性名 1=属性值 1
,............,
属性名 n=属性值 n
ENDWITH
【 例 8-4 】 用面向对象的方法设计一个程序,计算,
( 1) S=1+2+3+4+....+100
( 2) S=1+1/2+1/3+....+1/100
? 本例中设计了一个子类 Myadd_Class,Myadd_Class包
含三个属性和两个方法程序, 说明如下,
– 三个属性,
? S:存放结果和
? N:存放求和项数
? R1:求和方法标志, 当 R1=1时, 求整数和, 为其他值, 求分数

– 两个方法,
? S_sum:求和过程
? S_show:显示属性 S,即显示求和结果 。
? 程序如下,
? Myadd_Object=CreateObject('Myadd_Class') && 根据 Myadd_Class
派生一个对象
? Myadd_Object.r1=1 && 设置 Madd_Object对象的属性
? Myadd_Object.n=100
? Myadd_Object.S_sum && 调用方法 S_sum求和
? Myadd_Object.S_show && 调用方法 S_show下身结果
? Local Myadd
? Myadd_Object.r1=2
? Myadd_Object.S=0
? Myadd_Object.S_sum
? Myadd_Object.S_show
? RETURN
? DEFINE CLASS Myadd_class AS CUSTOM && 定义一个子类
Myadd_Class
? r1=0 && Myadd_Class 包含三个属性
? n=0
? s=0
? PROCEDURE S_sum && Myadd_Class的求和方法
? FOR i=1 to This.n
? IF This.r1=1 THEN
? This.s=This.s+i
? ELSE
? This.s=This.s+1/i
? ENDIF
? ENDFOR
? ENDPROC
? PROCEDURE S_show && Myadd_Class 的显示结果方法
?? This.s
? ENDPROC
? ENDDEFINE
8.3.3 事件驱动模型
? 1,事件是 OOP方法中驱动程序运行的引擎
? OOP与传统的面向过程的程序设计方法一个很
大的差别就是驱动程序组件运行的机制不同:
在面向过程的程序设计方法中,程序设计者要
设计一个主控模块来协调并驱动程序各组件
(过程、函数、模块)的运行,而在 OOP方法
中,则根本无需这样一个主控模块,各组件
(对象)的运行是用一种称为, 事件, 的机制
来驱动的
? 2、事件触发顺序
? 另一个问题是:有些事件似乎是同时发
生的,那么计算机按照怎样的顺序执行
这些事件的代码呢? Visual FoxPro 对事
件的响应有一个固定的顺序,课本表 8-6
列出了事件触发顺序