Implements
指定将在其出现的类中实现的接口或类。
语法:
Implements { InterfaceName | ClassName } [ , { InterfaceName | ClassName } ]…
- InterfaceName
- 接口的名称——twinBASIC中定义的 Interface 块,或引用类型库中的接口——其成员将由类中对应的成员实现。
- ClassName
- 将实现其默认接口的类的名称。
单个 Implements 语句可以用逗号分隔列出多个接口或类;这等价于为每个名称写一条 Implements 语句。经典VBA要求每条语句单独写。
接口是表示接口封装的成员(方法和属性)的原型集合;即它只包含成员过程的声明。类提供一个或多个接口的所有方法和属性的实现。类提供当每个函数被类控制器调用时使用的代码。所有类至少实现一个接口,该接口被视为类的默认接口。任何未显式为已实现接口成员的成员隐式为默认接口的成员。
当类实现接口时,类提供接口中指定的所有 Public 过程的自身版本。除了提供接口原型与实现过程之间的映射外,Implements 语句还使类接受指定接口ID的COM QueryInterface 调用。
实现接口或类时,必须包含所有 Public 过程。接口或类实现中缺少成员会导致错误。当未在某个已实现的过程中放置代码时,应引发适当的错误(Const E_NOTIMPL = &H80004001),以便实现的使用者知道某个成员未实现。
Implements 语句不能出现在标准模块中——它仅在 Class 块中有效。
twinBASIC增强功能
twinBASIC以多种方式扩展了经典VBA的 Implements。参见继承获取完整讨论;主要差异:
- 逗号分隔列表——一条 Implements 语句可以命名多个接口或类,如
Implements IFoo, IBar, IBaz。经典VBA要求每个接口单独一条 Implements 语句。 - 继承的接口——
Implements直接作用于派生接口(如Implements IFoo2,其中Interface IFoo2 Extends IFoo)。类不需要单独命名IFoo;基接口的QueryInterface自动满足。经典VBA不支持实现派生接口。 - 多重实现形式——单个成员可以通过过程头部后的
Implements <iface1>.<member>, <iface2>.<member>, …同时实现多个接口的方法。当多个接口声明相同成员且一个函数体应满足所有接口时,这很有用。 As Any参数——使用As Any参数声明的接口可以被实现(在实现类中用As LongPtr替换As Any)。经典VBA拒绝此用法。
INFO
在实现过程中使用 Private(或 Friend),以便接口方法不会同时成为实现类的默认接口的一部分。传统命名模式为 <InterfaceName>_<MemberName>。
示例
以下示例展示如何使用 Implements 语句使一组声明可用于多个类。通过 Implements 语句共享声明,两个类都不需要自己进行任何声明。示例还展示了接口的使用如何支持抽象:可以使用接口类型声明强类型变量。然后可以为其分配实现该接口的不同类类型的对象。
接口声明在一个名为 PersonalData 的类中:
Public Name As String
Public Address As String支持客户数据的代码在一个名为 Customer 的类模块中。注意 PersonalData 接口的实现使用了接口名 PersonalData_ 作为前缀命名的成员。
Implements PersonalData
' For PersonalData implementation
Private m_name As String
Private m_address As String
' Customer-specific
Public CustomerAgentId As Long
' PersonalData implementation
Private Property Let PersonalData_Name(ByVal RHS As String)
m_name = RHS
End Property
Private Property Get PersonalData_Name() As String
PersonalData_Name = m_name
End Property
Private Property Let PersonalData_Address(ByVal RHS As String)
m_address = RHS
End Property
Private Property Get PersonalData_Address() As String
PersonalData_Address = m_address
End Property
Private Sub Class_Initialize()
m_name = "[customer name]"
m_address = "[customer address]"
CustomerAgentId = 0
End Sub第二个类 Supplier 独立实现相同的接口,拥有自己的状态和 Class_Initialize。需要名称/地址访问的代码可以将变量声明为接口类型并接受任一类:
Private m_pd As PersonalData
Public Property Set PD(Data As PersonalData)
Set m_pd = Data
End Propertym_pd 只能访问 PersonalData 的成员。Customer特有或Supplier特有的成员通过它不可见——将对象赋值给按接口类型声明的变量提供了多态行为。