实现属性

本主题继续讨论“创建和实现接口”开始的代码示例,将属性添加到用 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

当然,也可以用更常用的单位来返回属性值,比如犬类的寿命。

详细信息   已经正在到处引申接口和对象的概念,把它们看作是同样的东西,而表面看来则是把对对象的引用放置到对象变量中,把对接口的引用放置到另一个对象变量中。“关于对象和接口的简要补充讨论”澄清许多问题。