Implements
Specifies an interface or class that will be implemented in the class in which it appears.
Syntax:
Implements { InterfaceName | ClassName } [ , { InterfaceName | ClassName } ]…
- InterfaceName
- The name of an interface — either an Interface block defined in twinBASIC, or an interface in a referenced type library — whose members will be implemented by the corresponding members in the class.
- ClassName
- The name of a class whose default interface will be implemented.
A single Implements statement can list several interfaces or classes separated by commas; this is equivalent to writing one Implements statement per name. Classic VBA requires a separate statement for each.
An interface is a collection of prototypes representing the members (methods and properties) that the interface encapsulates; that is, it contains only the declarations for the member procedures. A class provides an implementation of all the methods and properties of one or more interfaces. Classes provide the code used when each function is called by a controller of the class. All classes implement at least one interface, which is considered the default interface of the class. Any member that isn’t explicitly a member of an implemented interface is implicitly a member of the default interface.
When a class implements an interface, the class provides its own versions of all the Public procedures specified in the interface. In addition to providing a mapping between the interface prototypes and the implementing procedures, the Implements statement causes the class to accept COM QueryInterface calls for the specified interface ID.
When implementing an interface or class, all the Public procedures involved must be included. A missing member in an implementation of an interface or class causes an error. When code is not placed in one of the implemented procedures, raise the appropriate error (Const E_NOTIMPL = &H80004001) so a user of the implementation understands that a member is not implemented.
The Implements statement can’t appear in a standard module — it is valid only in a Class block.
twinBASIC enhancements
twinBASIC extends classic VBA’s Implements in several ways. See Inheritance for the full discussion; the headline differences:
- Comma-separated list — one Implements statement can name multiple interfaces or classes, e.g.
Implements IFoo, IBar, IBaz. Classic VBA requires a separate Implements statement for each. - Inherited interfaces —
Implementsworks directly on a derived interface (e.g.Implements IFoo2whereInterface IFoo2 Extends IFoo). The class need not nameIFooseparately;QueryInterfacefor the base is satisfied automatically. Classic VBA does not support implementing derived interfaces. - Multiple-implementation form — a single member can implement methods on several interfaces at once via
Implements <iface1>.<member>, <iface2>.<member>, …after the procedure header. This is useful when several interfaces declare the same member and one body should satisfy all of them. As Anyparameters — interfaces declared withAs Anyparameters can be implemented (substitutingAs LongPtrforAs Anyin the implementing class). Classic VBA rejects this.
Note
Use Private (or Friend) on the implementing procedures so that the interface methods don’t also become part of the implementing class’s default interface. The conventional naming pattern is <InterfaceName>_<MemberName>.
Example
The following example shows how to use the Implements statement to make a set of declarations available to multiple classes. By sharing the declarations through the Implements statement, neither class has to make any declarations itself. The example also shows how use of an interface supports abstraction: a strongly-typed variable can be declared by using the interface type. It can then be assigned objects of different class types that implement the interface.
The interface declarations are in a class called PersonalData:
Public Name As String
Public Address As String
The code supporting the customer data is in a class module called Customer. Note that the PersonalData interface is implemented with members that are named with the interface name PersonalData_ as a prefix.
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
A second class Supplier implements the same interface independently, with its own state and Class_Initialize. Code that needs name/address access can declare a variable as the interface type and accept either:
Private m_pd As PersonalData
Public Property Set PD(Data As PersonalData)
Set m_pd = Data
End Property
m_pd can only access the members of PersonalData. Customer-specific or Supplier-specific members are not visible through it — assigning an object to a variable declared by interface type provides polymorphic behavior.