发信人: pcbird()
整理人: hunter__fox(2002-03-16 22:58:08), 站内信件
|
引言
有很多软件开发产品都声称支持面向对象的编程(OOP),但其中大多数只是支持 可视对象(GUI)。Visual FoxPro 是一个全面面向对象的开发环境:一方面,它 的可视类功能非常强,并且十分灵活;另一方面,它还支持非可视类。实际上, 对非可视类的开发才是真正需要想象力和创造力的工作,因为众多面向对象的强 大功能是隐身于显示之下的。
定义
顾名思义,非可视类并不是用于显示的。例如,可以在表单上使用标签控件显示 一个“8”,因为“标签”是一个可视类;但若向表单中加入计时器,则它不会在 表单中显示,“计时器”是非可视类。
Visual FoxPro 中的非可视类通常都是自定义类 (Custom Class) 或者计时器类 (Timer Class) 的子类或派生类。一般情况下,它们不包含可显示的组件,但是 ,以后我们将看到,它们也可以包含可显示的组件。
创建非可视类的原因
在很多情况下需要使用非可视类,可以说,需要使用非可视类的场合与使用可视 类一样多。总的来说,可以使用非可视类:
维护代码
重用代码
增强已有功能
用于管理
可视类主要用于用户界面设计,而非可视类主要用于程序功能的管理。另外,在 讨论面向对象的系统开发时,经常被忽略的类 - 商业类,大多数也属于非可视类 。
非可视类的种类
包装类:
当我们谈论为管理任务而写的类时,会有多种不同的管理要求我们为其创建类, 其中一种类型的管理就是管理程序间的接口。例如,Visual FoxPro 代码和 .DL L、.FLL 或者其他别的函数库之间的接口管理。使用类来管理,可以简化函数库 的调用过程,增强调用函数的功能,对函数的定义,加载和错误处理进行封装隐 藏。
这个过程称为“用类包装已有的功能”,确切地说,我们称这些类为“包装类” 。
管理类:
另一种非可视类是用来管理其他类的。比如可以建立一个类来管理表单的多个实 例,我们可以在这个类中命名所有表单实例的标题,或完成其他功能。我们称这 样的类为“管理类”。
商业类:
商业类被设计用来模拟商业环境中的某个实体,例如顾客类。这些类是信息和行 为的综合体,为了解决商业实体(如,环境模型化、自动化)的问题。
商业类的任务总是经过仔细分析和认真设计才决定下来的,它的任务可能十分抽 象,在具体实现前要十分仔细地建模。商业类一般都具有如下功能:
从数据库检索信息
打印
存入数据库
在区分商业类的可视与非可视时存在一些困难,商业类可能、而且常常包含有可 视组件,或者它可能派生于某个可视类(如表单类),只不过在表单上添加了一 些适当的属性和方法程序。那么它到底属于哪一类呢?这就要视它创建对象的方 法而定。
首先让我们看一个简单的封装类的例子。
包装类
正如我们前面讨论过的,包装类用于管理(甚至增强)其他代码的功能。任何代 码都可被包装在一个类中。比如,您如果以前用早期版本的 FoxPro 创建了一个 过程库,现在就可以把它包装在一个类中。包装本身很简单,真正需要你动脑筋 的是确定哪些代码需要被包装到类中。
用类包装一样东西的主要目的是为了使这样东西更好用。最典型的包装对象是 . DLL 和 .FLL 库。这些函数库通常十分模糊,参数难于确定,而且需要另外编写 错误处理程序。比如,您在一段程序中需要使用 FOXTOOLS.FLL 库,而别人的程 序可能用 SET LIBRARY TO 命令释放了这个库,那么您该怎么办?您能总认为函 数一直有效吗?再调用一些 Windows API 函数(例如:从 .INI 文件中进行读或 写的函数)试一试,您会发现,学用这些函数十分困难。
当用一个类将其他一些代码包装后,类的开发者就可以控制 .DLL 或 .FLL 中的 哪些部分可供外部调用,以及如何调用,甚至可以控制它们返回什么值。
使用包装类有许多优点。首先,如果一个 .DLL 或 .FLL 是被包装在一个类中, 使用这个类的开发者就可以不用知道他或她正在使用的 DLL 或 .FLL 的基础部分 ,也没有必要去考虑加载 .DLL 或 .FLL 和注册其中函数的问题。
总之,减少了学习难度和编程时间。
下面是一个包装类的具体例子,它包装了 FOXTOOLS.FLL 函数库。FOXTOOLS.FLL 是随 Visual FoxPro 所发布的函数库。
* Program...........: FTOOLS.PRG
* Author............: Menachem Bazian, CPA
* Copyright.........: (c) Flash Creative Management, Inc. 1994, 95
* Project...........: COMMON
* Created...........: 11/29/1994
* Description.......: Wrapper class for FoxTools
* Major change list.:
*-- This is a wrapper class for FoxTools. The following functions have been added as
*-- methods to this class:
*--
*-- DriveType
*-- JustPath
*-- JustDrive
*-- AddBs
*-- CleanDir
*--
*-- A couple of quick notes here:
*--
*-- JustPath has been modified to add a backslash where necessary to t he return
*-- value.
*--
*-- CleanDir deals with the issue of directories specified with ..\. I t returns
*-- an "adjusted" directory name.
*--
*-- In all cases when running a FoxTools function, the class will chec k to make sure
*-- that FoxTools is still loaded (the user may have released on their own). If this
*-- class loads FoxTools, it released it when the object is released.
DEFINE CLASS ftools AS custom
PROTECTED lLoaded
PROCEDURE init
this.lLoaded = .F.
this.loadlib()
ENDPROC
PROCEDURE destroy
IF this.lLoaded
RELEASE LIBRARY (SYS(2004)+"foxtools.fll")
ENDIF
ENDPROC
PROCEDURE loadlib
IF !"FOXTOOLS" $ SET("library")
SET LIBRARY TO (SYS(2004)+"FOXTOOLS")
this.lLoaded = .T.
ENDIF
ENDPROC
FUNCTION drivetype(tcDrive)
LOCAL lnRetVal
lnRetVal = (drivetype(tcDrive))
RETURN lnRetVal
ENDFUNC
FUNCTION justpath(tcString)
LOCAL lcRetVal
lcRetVal = (this.addbs(justpath(tcString)))
RETURN lcRetVal
ENDFUNC
FUNCTION addbs(tcString)
LOCAL lcRetVal
lcRetVal = (addbs(tcString))
RETURN lcRetVal
ENDFUNC
FUNCTION cleandir(tcString)
RETURN(UPPER(sys(2027, tcString)))
ENDFUNC
PROCEDURE error (tnError, tcMethod, tnLine)
LOCAL lcMessage
tcMethod = UPPER(tcMethod)
DO CASE
CASE tnError = 1 && File not found
&& Cause by the library not loaded
this.loadlib()
RETRY
OTHERWISE
?? CHR(7)
lcMessage = "An error has occurred:" + CHR(13) + ;
"Error Number: " + PADL(tnError,5) + CHR(13) + ;
" Method: " + tcMethod + CHR(13) + ;
" Line Number: " + PADL(tnLine,5)
=MESSAGEBOX(lcMessage, 48, "Ftools Error")
ENDCASE
ENDPROC
ENDDEFINE
这个类展示了包装类的各种用途,下面我们分别介绍:
易于使用:封装错误处理
当库被加载到 Visual FoxPro 期间,可能会有别的对象将这个库从内存中释放了 ,所以再调用该库时会产生“找不到文件”错误。FTOOLS 类聪明地解决了这个问 题,该类的对象在初始化时自动加载 FOXTOOLS.FLL(若它还未被加载);如在调 用其中的函数前,这个库被释放了,Visual FoxPro 将产生一个 #1 错误(找不 到文件)并激活错误处理程序,在这段代码中重新调用 loadlib( ) 加载函数库 。这为开发者提供了使用 FoxTools 的简易方法,使得开发者无须考虑是否有人 释放了库。
增强现有功能:
FoxTools 中的函数 JustPast( ) 提取出文件名中的路径部分并把它作为字符串 返回,返回的字符串中的最后一个字符可能是反斜杠(路径分隔符),也可能没 有反斜杠。出于一致性考虑,在调用 JustPast( ) 方法程序的同时也调用了 Ad dBs( )。这样,如果字符串末尾没有反斜杠,会被加上,用户将得到统一的返回 值。这便是一个增强功能、提供给开发者简单、一致的返回值的例子。
增加功能:
CleanDir( ) 用于来调整包含“后退结点(..\)”的路径字符串。例如,路径字 符串“C:\WINAPPS\VFP\SAMPLES\DATA\..\GRAPHICS\”会被调整为等价的“C:\W INAPPS\VFP\SAMPLES\GRAPHICS\”,这个函数根本就没有调用 FOXTOOLS,但它的 功能却与这个类中的其他函数有关。将这个函数作为方法程序增加到类中,我们 就可以使开发者从一个地方得到所有的相关功能,而无须加载多个类。
创建和使用包装类的能力对软件开发是十分有利的。因为包装类屏蔽了复杂的实 现过程而对用户的功能没有影响。开发者的工作效率会大大提高,他们得到了合 手的工具,而不用去学习工具工作的细节。
管理类:
第二种常用的非可视类是“管理类”。这种类通常用于管理其他类的一系列实例 。例如:用一个类管理表单的多个实例以保证每个实例都能显示在屏幕的正确的 位置上,并且具有各自的标题(如 Document1、Document2 等)。
下面的例子中包括一个管理类和一个简单的表单类,管理类将管理表单的各个实 例。
* Program...........: MANAGER.PRG
* Author............: Menachem Bazian, CPA
* Copyright.........: (c) Flash Creative Management, Inc. 95
* Created...........: 05/03/95
*) Description.......: Sample Manager Class with Managed Form Class
* Major change list.:
*-- This class is designed to manage a particular form class and make
*-- sure that when the forms are run they are "tiled" properly.
DEFINE CLASS FormManager AS Custom
DECLARE aForms[1]
nInstance = 0
PROCEDURE RunForm
*-- This method runs the form. The instance of the form class
*-- is created in the aForms[] member array.
LOCAL lnFormLeft, llnFormTop, lcFormCaption
nInstance = ALEN(THIS.aForms)
*-- Set the Top and Left Properties to Cascade the new Form
IF nInstance > 1 AND TYPE('THIS.aForms[nInstance -1]') = 'O' ;
AND NOT ISNULL(THIS.aForms[nInstance -1])
lnFormTop = THIS.aForms[nInstance -1].Top + 20
lnFormLeft = THIS.aForms[nInstance -1].Left + 10
ELSE
lnFormTop = 1
lnFormLeft = 1
ENDIF
*-- Set the caption to reflect the instance number
lcFormCaption = "Instance " + ALLTRIM(STR(nInstance))
*-- Instantiate the form and assign the object variable
*-- to the array element
THIS.aForms[nInstance] = CREATEOBJECT("TestForm")
THIS.aForms[nInstance].top = lnFormTop
THIS.aForms[nInstance].left = lnFormLeft
THIS.aForms[nInstance].caption = lcFormCaption
THIS.aForms[nInstance].show()
*-- Redimension the array so that more instances of
*-- the form can be launched
DIMENSION THIS.aforms[nInstance + 1]
ENDPROC
ENDDEFINE
*-- This class is a form class that is designed to work with
*-- the manager class.
DEFINE CLASS TestForm AS form
Top = 0
Left = 0
Height = 87
Width = 294
DoCreate = .T.
BackColor = RGB(192,192,192)
BorderStyle = 2
Caption = "Form1"
Name = "Form1"
ADD OBJECT label1 AS label WITH ;
FontName = "Courier New", ;
FontSize = 30, ;
BackStyle = 0, ;
Caption = (time()), ;
Height = 61, ;
Left = 48, ;
Top = 12, ;
Width = 205, ;
Name = "Label1"
ENDDEFINE
有一点需要注意,表单的初始化是在 RUNFORM 方法程序中完成的,而不是直接使 用 Createobject( ) 函数,这就使管理类可以控制它所创建的对象。
管理类十分有用,他们允许用十分简单的方法封装代码,而这样的代码通常在初 始化一个对象时需要另外复制一份。
商业类:
商业类是商业实体(如,客户)的面向对象表示。这些类的功能根据特定对象在 商务活动中的不同行为而不同。
商业类的目的是进行多层抽象。在抽象的过程中,才可能发现商业对象的基本功 能,然后由此产生一个类。例如,商业对象的基本功能应该有:
从数据库中检索数据
在数据库表中移动(First,Last,Prev,Next)
显示
打印
通过这些功能可抽象出以下类:
DEFINE CLASS BaseBusiness AS custom
cAlias = ""
oData = .NULL.
PROCEDURE INIT
IF !EMPTY(this.cAlias) AND !used(this.cAlias)
=MessageBox("Alias is not open!", 16)
ENDIF
ENDPROC
PROCEDURE next
SELECT (this.cAlias)
SKIP 1
IF EOF()
GO BOTTOM
ELSE
this.readrecord()
ENDIF
ENDPROC
*-- Additional methods here for movement would mimic
*-- procedure NEXT
PROCEDURE readrecord
*-- This procedure is initially empty
SCATTER NAME this.oData
ENDPROC
*-- Additional methods for saving would follow mimicing
*-- procedure readrecord.
ENDDEFINE
要生成一个客户对象,我们只要按下列方法创建上述类的一个子类即可:
DEFINE CLASS customer AS basebusiness
cAlias = "Customer"
ENDDEFINE
将 customer 表中的字段作为 oData 的成员加入。假如以后由 customer 类生成 了一个 oCust 对象,customer 表中 cName 字段的数据可用 oCust.oData.cNam e 存取。
这样做使得您不用分别为每个商业类从头到尾地编程,您只要为它们中特殊的功 能编写代码。
结论
面向对象的程序设计在 Visual FoxPro 中已超越了图形化用户界面的范围,非可 视类是我们的 OOP 武器库中快速无故障系统开发的强有力的武器。
感谢
感谢 Flash Creative Management, Inc, Hackensack, NJ 等帮助提供了部分资 料。
本文档所包含的信息代表了在发表本文时,Microsoft Corporation 对本文中所 探讨问题的观点。由于 Microsoft 必须对不断变化的市场作出反应,本文不应被 解释为 Microsoft 的承诺,并且 Microsoft 也不能保证在发表本文之后,本文 所提供的信息一定准确。
本文的目的仅在于提供参考信息。Microsoft 对本文不作任何明示或暗示的保证 。
1996 Microsoft Corporation 版权所有。
FoxPro 和 Windows 均是 Microsoft Corporation 的注册商标,Visual FoxPro 是 Microsoft Corporation 的商标。
-- ==============================================
我是一只PC、PC鸟,
想要飞,却飞也飞不高 ...
-----------------------
[email protected]
==============================================
※ 来源:.月光软件站 http://www.moon-soft.com.[FROM: 202.102.155.12]
|
|