收藏 分享(赏)

VB类模块和标准模块使用和区别.doc

上传人:fmgc7290 文档编号:7609035 上传时间:2019-05-22 格式:DOC 页数:14 大小:48KB
下载 相关 举报
VB类模块和标准模块使用和区别.doc_第1页
第1页 / 共14页
VB类模块和标准模块使用和区别.doc_第2页
第2页 / 共14页
VB类模块和标准模块使用和区别.doc_第3页
第3页 / 共14页
VB类模块和标准模块使用和区别.doc_第4页
第4页 / 共14页
VB类模块和标准模块使用和区别.doc_第5页
第5页 / 共14页
点击查看更多>>
资源描述

1、类模块和标准模块类模块和标准模块的不同点在于存储数据方法的不同。标准模块的数据只有一个备份。这意味着标准模块中一个公共变量的值改变以后,在后面的程序中再读取该变量时,它将得到同一个值。而类模块的数据,是相对于类实例(也就是,由类创建的每一对象)而独立存在的。 同样的,标准模块中的数据在程序作用域内存在,也就是说,它存在于程序的存活期中;而类实例中的数据只存在于对象的存活期,它随对象的创建而创建,随对象的撤消而消失。 最后,当变量在标准模块中声明为 Public 时,则它在工程中任何地方都是可见的;而类模块中的 Public 变量,只有当对象变量含有对某一类实例的引用时才能访问。 上面的比较,同

2、样适用于标准模块和类模块中的公共过程,用下面的例子可以说明。新建一个工程,并在“ 工程” 菜单中个添加一个标准模块和一个类模块,然后运行以下的代码: 把下面的代码放在 Class1 中:下面是 Class1 对象的一个属性。 Public Comment As String 下面是 Class1 对象的一个方法。 Public Sub ShowComment() MsgBox Comment, , gstrVisibleEverywhere End Sub 把下面的代码放在 Module1 中: 标准模块中的代码是全局的。 Public gstrVisibleEverywhere As Str

3、ing Public Sub CallableAnywhere(ByVal c1 As Class1) 下行改变一个全局变量,这是一个 Class1 实例的(属性) 只有传递给该过程的个别对象才受到影 c1.Comment = “Touched by a global function. “ End Sub 把两个命令按钮放在 Form1 上,并在 Form1 中添加以下的代码: Private mc1First As Class1 Private mc1Second As Class1 Private Sub Form_Load() 创建两个 Class1 类的实例。 Set mc1Firs

4、t = New Class1 Set mc1Second = New Class1 gstrVisibleEverywhere = “Global string data “ End Sub Private Sub Command1_Click() Call CallableAnywhere(mc1First) mc1First.ShowComment End Sub Private Sub Command2_Click() mc1Second.ShowComment End Sub 按 F5 键,运行该工程。当 Form1 加载时,它创建两个 Class1类实例,每个实例有自己的数据。同时,

5、Form1 设置了下面全局变量 gstrVisibleEverywhere 的值。 按下 Command1,调用全局过程并传递引用给第一个 Class1 对象。全局过程设置 Comment 属性,然后 Command1 调用ShowComment 方法显示该对象的数据。 正如图 1 所示,结果信息框演示了全局过程 CallableAnywhere如何设置对象的 Comment 属性,而且全局字符串在 Class1 内部是可见的。 图 1 第一个 Class1 对象的信息框按下 Command2,调用第二个 Class1 类实例的 ShowComment 方法。如图 9.7 所示,两个对象都访问

6、了全局字符串变量;然而,第二个对象的 Comment 属性是空的,因为对全局过程 CallableAnywhere的调用只改变第一个对象的 Comment 属性。 图 2 第二个 Class1 对象的信息框 重点:要避免类的代码依赖于全局变量,也就是标准模块中的公共变量。一个类的许多实例可以同时存在,所有这些对象在程序中共享全局数据。 在类模块代码中使用全局变量也违背了面向对象封装的编程原则,因为由这样的类所创建的对象并没有包含它们的所有数据。 静态类数据 有时,希望由一个类模块所创建的一些对象共享某个数据项。这就是所谓的静态类数据。 不能在 Visual Basic 类模块中实现真正的静态类

7、数据。但是,通过使用 Property 过程在标准模块中设置及返回 Public 数据成员的值,可以仿真静态类数据,如以下的代码: 只读属性返回应用程序的名字。 Property Get CommonString() As String 变量 gstrVisibleEverywhere 保存在 标准模块中,并声明为 Public。 CommonString = gstrVisibleEverywhere End Property 注意:在类模块中,对模块级的变量不能声明为 Static,Static 数据只能在过程中使用。 由 Property Let 过程(对于含有对象引用的属性,使用 Pr

8、operty Set)对标准模块数据成员赋予新的值,可以仿真非只读的静态类数据。然而,这种使用全局变量的方式违背了封装编程的原则,而且不推荐使用。 例如,变量 gstrVisibleEverywhere 可以在工程中任何地方赋值,甚至可以从别的类代码中赋值,只要该类具有 CommonString 属性。这样做能导致程序中非常微妙的错误。 对象模型 通过创建类模块并赋以属性和方法,就可以定义了类,接着就可以由该类创建任意数量的对象。如何记录所创建的这些对象呢? 记录对象最简单的办法,莫过于为创建的每个对象都声明一个对象变量。当然,这样对能够创建对象的数量就有了限制。可以在某个数组或者集合中保持多

9、个对象引用. 刚开始时,可能要定位窗体或标准模块中的对象变量、对象数组以及对象集合,就跟处理普通变量一样。但是,随着添加更多的类,可能会发现正使用的这些对象之间有明确的关系。 对象模型表达了包含关系 ,对象模型给出了基于对象程序的结构。通过定义程序中所使用的对象之间的关系,对象模型能够以一种使编程变得更容易的方式来组织对象。 一般来说,对象模型表达了这样一个事实:即某些对象是“更大的”,或者说比其它对象更重要一些可以认为这些对象是包含其它对象的对象,或者是由其它对象所组成的对象。 例如,在编程时,可能创建一个 SmallBusiness 对象来作为程序的核心。可能想让这个 SmallBusin

10、ess 对象包含与其关联的其它类型的对象,比如 Employee 对象和 Customer 对象。可能同时也希望它包含一个 Product 对象。可以定义四个类模块,分别叫做SmallBusiness、Employee、Customer 和 Product 类模块,并给它们中的每个添加合适的属性和方法,但是怎样在对象之间建立连接呢?有两种工具可以达到这个目的:即 Object 属性和 Collection 对象。下列这段代码显示了实现分层结构的一种办法: SmallBusiness 类模块中声明部分的代码。 Public Name As String Public Product As New

11、 Product Public Employees As New Collection Public Customers As New Collection 第一次引用 Product 属性时,将创建对象,因为已经把它声明为As new。例如,可以用下面的代码创建并设置 SmallBusiness 对象的Product 对象的名称和价格。 一个标准模块的代码。 Public sbMain As New SmallBusiness Sub Main sbMain.Name = “Velociraptor Enterprises, Inc. “ 在代码中首次使用 Product 变量时,创建 Pr

12、oduct 对象。 sbMain.Product.Name = “Inflatable Velociraptor “ sbMain.Product.Price = 1.98 . . 初始化并显示主窗体的代码。 . End Sub 注意: 用公共变量来实现一个对象属性并不简洁。如果在代码中的某处,将该属性设置为 Nothing 的话,可能会无意中将 Product 对象撤消。更好的办法是创建对象属性时,将之设置为只读属性,如下列代码所示。 为更强健的对象属性所编制的代码,该属性的存储是私有的, 因此不能从对象的外部将之设置为 Nothing。 Private mProduct As New Pr

13、oduct Property Get Product() As Product 首次调用这个属性时,mProduct 包含 Nothing, 因此 Visual Basic 将创建一个 Product 对象。 Set Product = mProduct End If 一对多对象关系 当对象之间关系是一对一时,对象属性可以正常工作。然而,经常出现的情况却是,某种类型的一个对象包含另一种类型的一些对象。在 SmallBusiness 对象模型中,Employees 属性是作为一个Collection 对象来实现的,因此,这个 SmallBusiness 对象可以包含多个 Employee 对象。

14、下列代码显示了怎样把新的 Employee 对象添加到这个集合中。 Public Function NewEmployee(Name, Salary, HireDate, _ ID) As Employee Dim empNew As New Employee empNew.Name = Name 对象的隐含创建。 empNew.Salary = Salary empNew.HireDate = HireDate 添加到集合中,并使用 ID 作为一个键。 sbMain.Employees.Add empNew, CStr(ID) 返回对新 Employee 的引用。 Set NewEmploy

15、ee = empNew End Function 在创建 SmallBusiness 对象所代表的企业雇员时,需要调用这个NewEmployee 函数多少次,就可以调用多少次。任何时候,通过遍历 Employees 集合,都可将现有的雇员列出。 注意: 再次说明,并没有非常强健的实现方法。比较好的实践是创建自己的集合类,并将它们按只读属性给出。这在“创建自己的集合类”中作了讨论。 提示: 在 Visual Basic 的专业版和企业版中,包括 Class Builder 实用工具,利用这个实用工具,可以产生实现对象模型时需要的大量代码。Class Builder 可创建强健的对象属性和集合类,

16、并且可以很容易地重新组织对象模型。 Parent 属性 具有对象的引用时,通过使用对象属性和对象集合,就可以到达这个引用所包含的对象。能够向分层结构的上层移动也是非常有用的,因为可以到达包含所引用对象的那个对象。向上移动通常是用 Parent 属性来完成的。 Parent 属性返回对象容器的引用。关于对象模型定位的讨论,请参阅“用部件编程” 中的 “定位对象模型”。提示 当把 Parent 属性赋给集合中的对象时,不要使用对 Collection对象的引用。这个对象真正的父是包含该集合的对象。如果 Parent属性指向了该集合,将不得不使用两级间接指针,才能到达真正的父也就是说,要用 obj.

17、Parent.Parent,而不是 obj.Parent。 Parent 属性、循环引用,以及对象拆卸 使用 Parent 属性的一个最大问题是它们会造成循环引用。 “较大”的对象具有对所包含对象的引用,而被包含的对象通过其 Parent 属性也有引用,这样就创建了一个环。 在这幅图片上有什么错误?去除这些对象的办法,是在用对象完成工作后,释放所有对它们的引用。假设对 SmallBusiness 对象的引用是在一个名为 sbMain 的变量中,就象在本节主题前面讨论的那样,可能会写出象下面这样的代码: Set sbMain = Nothing 不幸的是,仍然有一个对 SmallBusiness

18、 对象的引用事实上,可能有许多引用,因为每个 Employee 对象的 Parent 属性都将包含对这个 SmallBusiness 对象的引用。 由于 SmallBusiness 对象的 Employees 集合包含有对每个 Employee对象的引用,因此任何对象都不会被撤消。 TearDown 方法 一个解决这个问题的办法是,把 TearDown 方法添加给该SmallBusiness 对象。这样,就可以将所有 SmallBusiness 对象的对象属性设置为 Nothing,同时也将所有 Collection 对象 (Employees, Customers)设置为 Nothing。

19、当 Collection 对象被撤消时,Visual Basic 就把它所包含的所有对象引用设置为 Nothing。如果没有对包含 Employees 和 Customers 集合中的 Employee 和 Customer 对象其它的引用,那么它们将被撤消。 当然,如果 Employee 对象是由更小的对象构成的,则将会存在其父对象所具有的同样的循环引用问题。在那种情况下,必须将一个 TearDown 方法赋给 Employee 类。要做的事情并不仅仅是将Employees 的 Collection 对象设置为 Nothing,SmallBusiness 对象还将不得不首先遍历该集合,调用每

20、个 Employee 对象的 TearDown 方法。其它问题即使这样,也并非所有对象都能被撤消。如果在程序的某个地方还有一些变量,这些变量仍然包含对 SmallBusiness 对象,或者对SmallBusiness 对象所包含的任何对象的引用,那么这些对象将不会被破坏。程序中必须有一部分清理代码,以确保各个地方的所有对象变量都被设置为 Nothing。为了测试是否正发生这种情况,可能需要将一些调试代码添加到对象中。例如,可以将下列代码添加到标准模块中:全局调试集合Public gcolDebug As New Collection 全局函数,赋给每个对象一个唯一的 ID。 Public F

21、unction DebugSerial() As Long Static lngSerial As Long lngSerial = lngSerial + 1 DebugSerial = lngSerial End Function 在每个类模块中,都可以加入类似下面这样的代码。每个类在“Product”出现的地方提供它自己的名字。 调试 ID 的存储。 Private mlngDebugID As Long Property Get DebugID() As Long DebugID = mlngDebugID End Property Private Sub Class_Initiali

22、ze() mlngDebugID = DebugSerial 将一个字符串登录项添加到全局集合中。 gcolDebug.Add “Product Initialize; DebugID= “ _ & DebugID, CStr(DebugID) End Sub Private Sub Class_Terminate() 删除字符串登录项,这样,就会知道对象不再存在了。 gcolDebug.Remove CStr(DebugID) End Sub 随着每个对象的创建,该对象将一个字符串放到全局集合中;当该对象撤消时,将删除该字符串。在任何时候,都可以遍历全局集合,看看什么对象还没有撤消。详细信息 ActiveX 部件中的全局数据,与普通程序中的处理方式不同。 如果有 VBP 或 VBE,请参阅 部件工具指南 中的“创建 ActiveX部件”, “部件设计的一般准则 ”中的“标准模块与类模块 ”。

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 企业管理 > 管理学资料

本站链接:文库   一言   我酷   合作


客服QQ:2549714901微博号:道客多多官方知乎号:道客多多

经营许可证编号: 粤ICP备2021046453号世界地图

道客多多©版权所有2020-2025营业执照举报