第9章创建和使用自己的类
类是具有多态性的用户定义类型。封装将代码和数据组织在同一个类模块中,使得对象能保护和验证其中的数据。借助创建对象的类能将数据和过程组织成一个整体。本章介绍类如何增强代码的活力,如何导致新的编程方法的产生。
9.1 创建自己的类
在VB中创建自已的类是通过在工程中添加类模块,然后设计类模块的相关代码实现的。本节讨论类的用途和在工程中定义类模块的过程。
9.1.1 类的作用
用户定义类型是一个使相关数据项成组的强大工具。例如,假设我们定义一个名为Point 的用户定义类型:
Public Type Point
x As Integer
y As Integer
End Type
可以声明一个Point类型的变量p,然后编写两个过程,一个为setvalue,用于给p的各个字段赋值;另一个为display,用于显示其值。这些代码如下:
Dim p As Point
Public Sub setvalue(ByVal a As Integer, ByVal b As Integer)
p.x = a
p.y = b
End Sub
Public Sub display()
MsgBox "(" + Str(p.x) + "," + Str(p.y) + ")"
End Sub
面向对象的编程通过将数据和过程结合成一个单一实体解决了上述问题,当把上面的用户定义类型Point变成一个CPoint类时,其数据变成了私有型,访问它们的过程移到类中并变成了属性和方法。这就是所谓的封装,也就是说,对象是一个包括代码和数据的单元。
当从CPoint类创建一个变量(即创建该类的一个对象)时,访问其数据必须通过构成
第9章创建和使用自己的类 201
其接口的属性及方法。
现在,暂不要考虑如何将过程放进类中,也不要考虑如何理解属性过程和私有变量的
语法。重要的是要记住,可以定义一个对象来封装数据和确保数据的可靠性。
9.1.2 定义类模块
在VB中通过“类模块”来创建类。我们以一个例子说明如何使用类模块定义类,还将
讨论如何为新的类创建属性和方法,并演示对象是如何创建和撤销的。
【例9.1】创建一个工程并在其中添加一个类模块Class1和一个窗体Form1,共同实
现用户输入的一个字符串的逆转。
首先打开一个新的“标准.EXE”工程,建立一个工程名为“工程1”的工程,在“工
程”菜单中选中“添加类模块”,插入一个类模块Class1。开始时,该类模块窗口是空白
的,我们可以输入相应的类定义代码,如图9.1所示是创建的Class1类模块的代码。
图9.1 类Class1创建窗口
该类定义了一个全局变量Name和一个过程ReverseName,该过程用于逆转Name指定的
字符串。
类模块有两个事件:Initialize和Terminate。从类模块的“对象”下拉列表中,选择“类”
便在“过程”列表中显示这2个事件的事件名。一般Initialize事件包含了对象创建时所需的
所有代码。Terminate事件包含撤销对象后进行清理的所有代码。本例不设计这两个事件过
程。
在该工程中添加一个普通的窗体Form1,在其中添加两个标签label1和label2,它们的标
题分别为“原来的字符串”和“逆转后字符串”;再添加两个文本框text1和text2;最后添
加一个命令按钮command1,其标题为“逆转”,并在该命令按钮上设计如下事件过程:
Private Sub Command1_Click()
Set myobject = New Class1
myobject.Name = Text1.Text
myobject.ReverseName
Text2.Text = myobject.Name
Basic程序设计导学
202 Visual
End Sub
本窗体的设计屏幕如图9.2所示。启动本工程,出现Form1窗体的屏幕,在文本框text1中输入字符串“0123456789”,然后单击“逆转”命令按钮,则文本框text2中出现字符串“9876543210”,如图9.3所示。
图9.2 Form1窗体设计界面
图9.3 Form1窗体执行界面
我们从上述Command1_Click()事件过程代码来讨论类的使用方式。第一行语句用于创建类Class1的一个对象myobject。这个对象中的Name变量变成私有变量,必须加上“myobject.”前缀才能使用。第二行语句给该变量赋初值。第三行语句调用myobject对象的ReverseName方法将Name变量之值逆转。第四行语句将变量Name的值在文本框text2中显示出来。
类模块和标准模块的不同点在于存储数据方法的不同。标准模块的数据只有一个备份,这意味着标准模块中一个公共变量的值改变以后,在后面的程序中再读取该变量时,它将得到同一个值。而类模块的数据,是相对于类实例(也就是由类创建的每一个对象)而独立存在的。
同样,标准模块中的数据在程序作用域内存在,也就是说,它存在于程序的存活期中;而类实例中的数据只存在于对象的存活期,它随对象的创建而创建,随对象的撤销而消失。
最后,当变量在标准模块中声明为Public时,则它在工程中任何地方都是可见的;而类模块中的Public变量,只有当对象变量含有对某一类实例的引用时才能访问。因此,在类模块中所有用于外部调用的变量或过程都要定义为Public型,否则在外部无法调用它们。
第9章创建和使用自己的类 203
9.2 在类中添加属性和方法
类的默认接口由类的属性、方法和事件组成。与此相对应的是类的内部私有数据、过
程和函数。它们被类的封装隐藏起来。属性、方法和事件对外界是可见的。一般来说,属
性表示对象的数据,方法表示对象能执行的动作。或者说,属性提供了对象的描述,而方
法则是它的行为。
注意:事件不属于默认接口。事件是调出接口(即该接口可连接其他对象),而
属性和方法属于调入接口(即该接口的成员被其他对象引用)。
9.2.1 向类中添加属性
定义类属性的最简单的方法,是向类的模块添加公共变量。例如,只要在名为Student
的类中声明两个公共变量,可非常简单的定义该类的属性:
Public name As String
Public age As Integer
给类创建私有数据也很简单,只须声明一个Private变量,它就能被该类模块中的编码
所访问:
Private f As Single
Private c As Single
1. 数据隐藏
数据隐藏是指保护对象的部分数据,而其余数据则以属性形式公开。这是面向对象的
简单的vb程序代码封装原则的一个方面。
数据隐藏可以改变类而不影响已存在的编码。例如,将Class类的私有变量x的类型从
Integer改变为Long,而不会改变调用Class对象已存在的编码。
数据隐藏也允许定义只读属性。例如,可用Property Get属性过程返回一个私有变量,
这就产生了属性过程。下一小节详细讨论属性过程。
2. 属性过程
如果只能通过声明公共变量来创建属性,那么就不能在更高层次上实现数据隐藏。例
如,一个类Class有一个公共属性x,myobject是该类的对象,我们可以使用myobject.x将该
属性设置为任意值。为了达到更高的数据隐藏,VB提供了属性过程,只能通过属性过程来
获取属性值和对属性值进行修改。
实际上,当设置或检索属性值时,VB就执行对应属性过程的代码。
204 Visual
Basic程序设计导学
【例9.2】创建一个类Class2说明属性过程的使用。
在本工程中添加一个类模块,并包含以下一段代码:
'pn为存储n属性的私有数据
Private pn As Integer
Public Property Get n() As Integer
n = pn
End Property
Public Property Let n(ByVal Newn As Integer)
If (Newn <= 0) Then
MsgBox "n值不能小于等于0", vbOKOnly, "信息提示"
Else
pn = Newn
End If
End Property
假设有一个名为myobject的变量,引用Class2对象。当执行x=myobject.n代码时,就会调用Property Get过程,返回存于类模块私有变量pn的值。当执行myobject.n=10代码时,将调用Property Let过程。
Set myobject = New Class2
myobject.n = 10 '调用Property Let过程使pn=10
x=myobject.n '调用Property Get过程将pn赋给n使x=10
从中看到,属性过程可允许对象保护并验证自己的数据。这是使用公共变量的属性不能实现的。
9.2.2 属性过程与公共变量的比较
属性过程具有封装功能,它是如此强大的工具,以致于有时会觉得公共变量有点没用。对于编程来说答案是“有时是”。以下是一些基本原则。
(1)以下情况应使用属性过程:
·属性为只读,或一旦设置就不能改变。
·属性已设置的值需要验证。
·超出特定范围的值,例如,负数虽符合属性的数据类型,但属性如果允许这样的假设值出现,就会导致程序出错。
·属性的设置可导致一些对象状态的明显变化,例如Visible属性。
·属性设置可改变内部变量或其他属性的值。
(2)以下情况应使用只读属性的公共变量:
·属性是自验证类型。例如,如果把一个不是True或False的值赋给Boolean变量,
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论