为了阻止类的外部使用者(比如模块1中的代码)随意来修改Person类的性别(Gender)属性,我们要学会使用另外一种定义类的属性(Property)的办法。
首先,我们将Public Gender As String 改为Private mstrGender As String,这样性别属性就被保护起来,外部使用者无法直接访问了。(你可能会问:“mstr”是什么?这其实就是程序员在定义变量的时候,约定的一个习俗。“m” 代表模块级(Module)变量,“str”是“String”的缩写。这样,当mstrGender这个变量出现在代码的其他地方时,我们一看前缀“mstr”就知道这是一个模块级的字符型变量。前几篇为了简化,没有变量命名规则的考虑,从本篇开始,我们会慢慢规范起来)
现在类的外部使用者再也不能直接访问修改mstrGender变量了,但是我们还是希望外部访问者能获取性别方面的信息,那该怎么弄呢?我们需要学习类模块中的两个新技能:Public Property Get / Public Property Let (还有一个类似的技能 Public Property Set 会在将来介绍)
Public是公有的意思,有了它,类的外部使用者才能访问。Property是属性的意思。Get是获取,Let是赋值。所以 Public Property Get是获取类的某个属性,Public Property Let是给某个属性赋值。我们修改Person类的代码如下:
Option Compare Database Option Explicit Public Name As String Private mstrGender As String Public Situation As String 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 Gender() As String Gender = mstrGender End Property Public Property Let Gender(lstrGender As String) If mstrGender = "" Then mstrGender = lstrGender Else MsgBox "性别一旦设定,就无法修改" End If End Property
25-27行的代码,为类定义了一个获取性别(Gender)的属性。我们直接将类的私有变量mstrGender的值直接返回给访问者。
29-35行的代码,为类定义了一个设置性别(Gender)值的属性。(参数“lstr”中的“l”代表List,参数列表的意思)当你给性别赋值的时候,首先会检查mstrGender的值是否为空字符串,如果是,就直接赋值。如果不是,说明之前已经被赋值过了,就弹出对话框提示你不能修改。(实际项目中,一般不会用对话框来提示类的使用者,而是通过触发一个事件的方式来与类的使用者做信息的传递。)这样,性别属性就不再让类的外部使用者随意修改了。你只能为性别赋值一次,你可以叫这种属性为“只写一次属性”。
我们来看看类的使用效果,在模块1中,我们修改代码如下:
Option Compare Database Option Explicit Sub test() Dim objperson As Person Set objperson = New Person objperson.Name = "赵冰冰" objperson.Gender = "女" objperson.Speak MsgBox "修改前性别:" & objperson.Gender objperson.Gender = "男" MsgBox "修改后性别:" & objperson.Gender End Sub
第12行和14行代码都是获取性别属性,第13行代码是对性别属性赋值。我们运行一下该代码,会依次弹出4个对话框
通过这种方式来定义类的属性,我们既能够保护类的私有变量不受到外部使用者的随意修改,也能够提供在我们允许的情况下访问和修改类属性的途径。
作为一个有经验的Access VBA开发人员,如果你掌握了这种定义类属性的方式,你可以开更多的脑洞,比如,如果在类中,将Public Property Get去掉,只保留Public Property Let会怎么样?或者反过来,将Public Property Let去掉,只保留Public Property Get又会怎么样?另外,29-35行代码,严格来讲,不能称之为“只写一次属性”,如果你第一次将性别赋值为空字符串””,那么你第二次还能再赋值。如果要设计一个真正的“只写一次属性”,你该怎么做?这些问题先留给有钻研精神的你思考吧。