Table of Contents

5.2.4 Class Module Declarations

Note

This section describes the implementation of MS-VBAL §5.2.4 Class Module Declarations.

Class modules defined in workspace source code have no means to inherit another class module in the Object-Oriented Programming sense of inheritance (RD-VBAL §2.4.2 Non-intrinsic Types).

A public Enum and a public user-defined type declared in a class module reach the project scope. A class module's other members need an instance to be reached through, but a declared type needs none (RD-VBAL §5.2.3 Module Declarations, §5.2.3.3 and §5.2.3.4).

5.2.4.1 Non-Syntactic Class Characteristics

Note

This section describes the implementation of MS-VBAL §5.2.4.1 Non-Syntactic Class Characteristics.

VBClassModuleSymbol.AutomationKind (VBAutomationKind) distinguishes an Automation-capable class module from an IUnknown-only class module:

AutomationKind Class module
Dispatch Automation-capable (VT_DISPATCH). This is the default.
Unknown IUnknown-only.

Every RD-VBA class module has AutomationKind Dispatch (VT_DISPATCH). See RD-VBAL §6.1.1 Predefined Enums (§6.1.1.16 VbVarType).

5.2.4.1.1 Class Accessibility and Instancing

Note

This section describes the implementation of MS-VBAL §5.2.4.1.1 Class Accessibility and Instancing.

The accessibility and instancing of a class module are determined by two module attributes (RD-VBAL §3.1.1 Attributes, §3.1.1.2 and §3.1.1.3):

Attribute Determines Value
VB_Exposed Whether a class module is visible at all to a referencing project. False for private modules, True for public modules.
VB_Creatable Whether a class module can be directly instantiated using a New (or CreateObject) expression from a referencing project. Must be False in a VBA module. May be True in a VB6 module, for RD-VBA clients that support the VB6 language.

A public module may be consumed by a referencing project. Whether a new instance of a public module can be created outside the enclosing project that defines it depends on the value of its VB_Creatable attribute.

A not-creatable class module can only be directly instantiated within the project it is defined in (the enclosing project). An instance of a not-creatable class may be consumed by any referencing project if the class module is exposed.

👉 Together, VB_Creatable and VB_Exposed determine the instancing mode of a class module:

Instancing mode VB_Exposed VB_Creatable
Private False False
PublicNotCreatable True False
PublicCreatable True True

The PublicCreatable instancing mode is not a legal VBA configuration. RD-VBA implementations may allow it, with semantic flags issued, if the host environment is configured to allow building library projects.

5.2.4.1.2 Default Instance Variables Static Semantics

Note

This section describes the implementation of MS-VBAL §5.2.4.1.2 Default Instance Variables Static Semantics.

The VB_PredeclaredId attribute (RD-VBAL §3.1.1 Attributes, §3.1.1.6) determines whether the environment host declares a global auto-object instance of the class with a predeclared ID. The identifier name of that global auto-object is the same as the name of the class module it is a predeclared instance of.

Static Semantics

The static semantics of VB_PredeclaredId are modeled:

👉 Deferred class types cannot be presumed to have a default instance (RD-VBAL §2.4.4 Deferred Types).

It is invalid for the default instance variable to be the target of a Set assignment, whatever is assigned to it (MS-VBAL §5.2.4.1.2; see RD-VBAL §5.4.3.9 Set Statement).

Runtime Semantics

In MS-VBA:

  • Setting an auto-object (predeclared instance) to Nothing destroys its internal state.
  • An auto-object reference is re-created as soon as it is referred to, including within an Is Nothing reference check.
Note

Not implemented. The run-time behavior of the default instance (it is never Nothing; it is re-created on reference) is not modeled.

5.2.4.2 Implements Directive

Note

This section describes the implementation of MS-VBAL §5.2.4.2 Implements Directive.

The Implements directive specifies that the (class) module implements an interface class (RD-VBAL §3.1 Attributes and Directives).

If a class module specifies any Implements directives, the interfaces specified by those directives are included in the class type's SuperTypes array (VBClassType; RD-VBAL §2.4.2 Non-intrinsic Types).

A class module also implements Class implicitly, which is among its implemented interfaces without a directive (RD-VBAL §5.3.1.10). The directives below are the ones the source writes: its ImplementedInterfaceNames.

Static Semantics

ImplementsSemantics checks the directives of a class module and what they require of it.

  • The class a directive names must exist (VBC09311 otherwise, as for any type that does not), cannot be the class of the module itself, and cannot be named by more than one directive of the module. A class whose public variables or methods have an underscore in their names cannot be an interface class, and the implemented interface name prefix of an interface, its name and an underscore, cannot begin that of another: VBC09328.
  • The module must declare an implemented name declaration, InterfaceName_MemberName, for each public method of the interface class, of the same kind, and for each public variable the property accessors its declared type calls for: a Property Get and a Property Let, a Property Set in place of the Let when the variable is an Object or a class, and all three when it is a Variant: VBC09329. The Private members of the interface class are not part of its interface.

What an implemented name declaration must be is RD-VBAL §5.3.1.9.

What is wrong with a directive is reported where the directive is written: the class module symbol carries the range of each directive (VBClassModuleSymbol.ImplementedInterfaceRanges, one for each of the ImplementedInterfaceNames), and an interface the module does not implement completely is reported at the directive that names it. A symbol that was not read from source has no ranges, and is reported at the module.

A directive in an extensible module (VB_Extensible = True, RD-VBAL §3.1.1.8) is invalid: VBC09328.

The environment host learns of the directives from the language server: DefineSymbolsParams.ImplementedInterfaceNames carries the interface names a module's directives name, and the host composes the module's class symbol from them and from the members it has been sent (ISessionSymbols.TryComposeClassModule), resolving the interfaces again over every class module it knows whenever one is composed, so the order the modules are defined in does not matter.

Warning

Extensible ("document") modules cannot specify any Implements directives.

MS-VBA does not strictly enforce this rule. In MS-VBA, an Implements directive in an extensible module can cause host application instabilities, source project corruption, and host application crashes.

RD-VBA must explicitly and statically deny Implements directives in extensible modules, as a normal compile-time error.

5.2.4.3 Event Declaration

This section corresponds to MS-VBAL §5.2.4.3 Event Declaration.

An Event declaration defines an event member of the class module. It is a VBEventMemberSymbol: its name, and its parameters, which describe the arguments a RaiseEvent (RD-VBAL §5.4.2.20) must give and the parameter list a handler must have (RD-VBAL §5.3.1.8); it defines no variable. An Event without an access modifier is Public. VBClassModuleSymbol.Events lists them, and FindEvent finds one by name, without regard to case.

The event symbols and their parameters are among the member descriptors the environment host receives, so a class's events are known where RaiseEvent runs.

An event name must be unique within the class module, reported as a duplicate declaration (VBC09303) when it is not, and must not contain an underscore, which is what separates a handler's variable from its event: VBC09325. Both are reported by ClassModuleEventSemantics.


⏮️ RD-VBAL §5.2.3 Module Declarations | ⏭️ RD-VBAL §5.3 Module Code Section Structure