本主题继续讨论“创建和实现接口”开始的代码示例,将属性添加到用 Flea 和 Tyrannosaur 类所实现的 Animal 接口中。当然,在开始该主题前,阅读一下那个主题是有帮助的。
假设要将 Age 属性赋予 Animal 类—通过将一个 Public 变量添加到声明部分:
Option Explicit
Public Age As Double
现在,在 Tyrannosaur 和 Flea 类的代码模块的“过程”下拉菜单上,将包含实现 Age 属性的属性过程,如下图 9.10 所示。
图 9.10 属性过程的实现
这里图示了本章前面的“向类中添加属性”中的一个要点。严格说来,用公有变量实现属性对于编程者来说是很方便的。此含义的背后,Visual Basic 是用一对属性过程来实现该属性。
必须实现两个过程。通过在私有数据成员中保存值,实现属性很容易,如下所述:
Private mdblAge As Double
Private Property Get Animal_Age() As Double
Animal_Age = mdblAge
End Property
Private Property Let Animal_Age(ByVal RHS As Double)
mdblAge = RHS
End Property
私有数据成员是一个实现细节,必须自己添加。
注意 当 Implements 为 Property Set 或者 Property Let 提供模板时,并没有任何办法来确定最后一个参数的名字,因此代之以名字 RHS,如上述代码示例所述。
在作为公有数据成员实现的属性上,没有对数据的有效性进行验证,但是那并不意味着不能将 Animal_Age 有效性验证的代码添加到 Property Let 中。例如,可能想分别为 Tyrannosaur 或者 Flea 限制其值为合适的年龄。
事实上,这意味着接口和实现的独立性。只要接口跟类型库中的描述相匹配,实现可以是任意的。
在进行下一步之前,从两个类模块中删除读写 Age 属性的实现部分。
当然,允许任意设定一个动物的年龄,是一种糟糕的对象设计。对象应该知道自己的年龄,并将这个年龄作为一种只读属性提供给用户。从 Animal 类中删除公有变量 Age
,并为只读年龄属性添加模板,如:
Public Property Get Age() As Double
End Property
现在,Tyrannosaur 和 Flea 类代码窗口的“过程”下拉菜单上,仅包含一个登录项,即 Age [PropertyGet]。对 Tyrannosaur 可这样实现:
Private mdblBirth As Double
Private Property Get Animal_Age() As Double
Animal_Age = Now - mdblBirth
End Property
上述代码返回 Tyrannosaur 按日计算的年龄。可以在 Tyrannosaur 类的 Initialize 事件中设置 mdblBirth
,如:
Private Sub Class_Initialize()
mdblBirth = Now
End Sub
当然,也可以用更常用的单位来返回属性值,比如犬类的寿命。
详细信息 已经正在到处引申接口和对象的概念,把它们看作是同样的东西,而表面看来则是把对对象的引用放置到对象变量中,把对接口的引用放置到另一个对象变量中。“关于对象和接口的简要补充讨论”澄清许多问题。