我们的第一个类的羽翼逐渐丰满,本篇介绍的内容将让它变得更加专业。
不知道你注意到没有,Person类中对性别(Gender)属性的设计存在一点缺陷。我们用私有模块级字符串变量mstrGender来保存性别数据,既然是一个字符串变量,那就可以往里面保存任何字符串数据,比如“女”,“女性”,“Female”。虽然字面上都是同一个意思,但是写法上都不相同,你无法预料类的使用者会给mstrGender赋什么值,这样就会造成信息处理和判断上的混乱。作为一个专业的类的设计者,你必须提供一套规范的取值范围。
作为一个有一定经验的Access VBA开发人员,你肯定写过类似docmd.OpenForm “Form1”, acNormal 的语句来以正常的方式打开一个窗体。’acNormal’就是一个常量。我们在写这条语句的时候,IDE还会弹出智能窗口帮助我们选择相关的常量,如下图所示:
上图列示出来的7个常量,你通过常量名就知道各个常量的用意,另外你多半不会自己敲入一个不在这个列表中的其他常量。
这种在类中使用常量的方式是非常普遍的。你应该在很多地方已经看到过。现在我们就来介绍如何在自己的类中使用这种常量。
这种常量实际上是枚举类型(Enumeration)中的一个值。我们在Person类的头部,为性别属性定义一个枚举类型pGender
Public Enum pGender Female Male End Enum
为什么叫pGender?“p”代表类名“Person”,为什么要将类名缩写作为前缀?因为我们定义的是公有的(Public)枚举类型,这个枚举类型在整个项目范围内都是可见的,将类名缩写作为前缀有利于与其他类中的枚举类型相互区分。
为什么Female(女性)/ Male(男性)这两个常量没有给一个常量的值?比如Female = “女”?呃,是的,一般的常量在定义的时候,需要给定一个常量值,可以为各种类型,比如Const PI As Double = 3.14,就是双精度型。但是枚举类型常量很特殊,它只能是长整形(Long)比如Female = 0。但是我们这里连“=0”都没有写。如果什么都没写,叫表示“从0开始,依次加1”,所以上述代码与下述代码是一样的
Public Enum pGender Female = 0 Male = 1 End Enum
你可以在立即窗口中测试一下“?pGender.Female”。当然如果你有特殊考量,你可以让Female等于其他的值,比如3,如果没给Male设置值,那么Male就在3的基础上加1,等于4。
好了,枚举类型的定义就介绍到这里。我们来看看如何使用它。
有了pGender这个类型,我们就可以将性别属性定义为这种类型了。我们将Private mstrGender As String 改为Private menumGender As pGender (enum是枚举类型Enumeration的缩写),将Gender的读写属性做相应修改,相关代码最后效果如下:
' '中间代码被忽略 ' Private menumGender As pGender ' '中间代码被忽略 ' Public Enum pGender Female Male End Enum ' '中间代码被忽略 ' Public Property Get Gender() As pGender Gender = menumGender End Property Public Property Let Gender(lenumGender As pGender) Static blnFlag As Boolean If blnFlag = False Then blnFlag = True menumGender = lenumGender Else MsgBox "性别一旦设定,就无法修改" End If End Property ' '中间代码被忽略 '
有了这些修改以后,我们在类的测试代码中,就会发现不一样的效果了,如下图
这样,类的使用者(模块1中的测试代码)在给性别赋值的时候,IDE的智能提示就会自动显示出来,供其选择。
类中的枚举常量使用起来非常简单,但是它极大的增加了类的友好性,也是开发人员专业性的直观体现。是一项投资回报率非常高的技能。
最后,按惯例,将最终全部代码贴给大家。
'Person 类代码 Option Compare Database Option Explicit Private mstrName As String Private menumGender As pGender Private mstrSituation As String Private mdatDOB As Date Public Enum pGender Female = 0 Male = 1 End Enum Public Sub Speak() Select Case Situation Case "一般" MsgBox Left(Name, 1) & "小姐" Case "正式" MsgBox Left(Name, 1) & "女士" Case "撩" MsgBox "小姐姐" Case Else MsgBox Name End Select End Sub Private Sub Class_Initialize() Situation = "一般" End Sub Public Property Get Name() As String Name = mstrName End Property Public Property Let Name(lstrName As String) If Len(lstrName) <= 4 Then mstrName = lstrName Else MsgBox "姓名不能超过4个字符" End If End Property Public Property Get Gender() As pGender Gender = menumGender End Property Public Property Let Gender(lenumGender As pGender) Static blnFlag As Boolean If blnFlag = False Then blnFlag = True menumGender = lenumGender Else MsgBox "性别一旦设定,就无法修改" End If End Property Public Property Get Situation() As String Situation = mstrSituation End Property Public Property Let Situation(lstrSituation As String) mstrSituation = lstrSituation End Property Public Property Let DOB(ldatDOB As Date) Static blnFlag As Boolean If blnFlag = False Then blnFlag = True mdatDOB = ldatDOB End If End Property Public Property Get DOBtoString() As String DOBtoString = Format(mdatDOB, "YYYY年mm月dd日") End Property Public Property Get Age() As Integer Age = DateDiff("yyyy", mdatDOB, Date) End Property
'模块1 测试代码 Option Compare Database Option Explicit Sub test() Dim objperson As Person Set objperson = New Person objperson.Name = "赵冰冰" objperson.Gender = Female objperson.Speak MsgBox "修改前性别:" & objperson.Gender objperson.Gender = Male MsgBox "修改后性别:" & objperson.Gender objperson.DOB = #2/3/1995# Debug.Print objperson.DOBtoString '立即窗口值:1995年02月03日 Debug.Print objperson.Age '立即窗口值:23 objperson.DOB = #6/10/1995# Debug.Print objperson.DOBtoString '立即窗口值:1995年02月03日 End Sub