Атрибуты Visual Basic : что это такое и почему мы должны их использовать?

Visual Basic Attributes: What Are They and Why Should We Use Them?Данный материал является переводом оригинальной статьи "Christopher J. McClellan : VB Attributes: What are they and why should we use them?".

Знаете ли вы, что в ваших проектах Visual Basic есть код, который вы не видите в редакторе? Хотите увидеть его? (Конечно же, хотите!)

Итак, просто щелкните правой кнопкой мыши любой модуль и выберите пункт меню "Export File".

Visual Basic Export File from Project

Сохраните файл в удобном месте и откройте его в любом текстовом редакторе, например Notepad++.

Visual Basic Attributes in text editor

И здесь мы видим скрытый заголовок, который есть во всех ваших классах и модулях VBA. Однако, насколько известно, только три из них делают что-либо в Visual Basic.

  1. VB_Name
  2. VB_PredeclaredId
  3. VB_Exposed

VB_Name говорит само за себя, он хранит имя, которое вы ему дали, в окне свойств. VB_PredeclaredId намного интереснее. Если вы измените значение VB_PredeclaredId на true в файле класса, этот класс получит глобальный экземпляр по-умолчанию, когда ваш код запускается. Нынче, global - это плохо, все об этом знают, так что пользуйтесь с осторожностью, но эта возможность дает нам симулировать методы статического класса в нашем коде VBA. Что всё это значит? То, что мы можем получить доступ к методам класса без создания сперва нового экземпляра класса. Мы можем получить доступ к методам через наш глобальный дефолтный экземпляр.

Так, вместо:

Dim math As New clsMath
math.Add 1, 2

Можно сделать:

Math.Add 1, 2

Понятно, что пример так себе. Мы могли бы выполнить приведенный выше фрагмент кода с помощью обычного модуля, но он действительно позволяет нам делать несколько прикольных вещей.

Я не буду особо касаться оставшегося атрибута VB_Exposed, кроме как скажу, что он содержит значение  свойство экземпляра класса. 1 == false. 2 == true. В VBA нет других значений. Они не были перенесены из VB6.

Но подождите, есть еще кое-что...

Это только заголовок, атрибуты уровня модуля. Существует также ряд атрибутов, которые можно применять к переменным (полям), свойствам и процедурам модуля. Синтаксис переменных немного отличается, так что начнем с него.

VB_VarUserMemId: Определяет порядок переменных в Object Broswer. Значение 0 (ноль) объявляет переменную членом класса по умолчанию.

VB_VarDescription: Значение этого атрибута будет отображаться в Object Broswer.

Итак, поместив этот код в наш модуль и повторно импортируя его обратно в наш проект, мы получим это в Object Browser:

Public FooCount As Integer
Attribute FooCount.VB_VarDescription = "Specifies the number of Foos"

 

VB Object Browser and VarDescription

Это позволяет нам разместить нашу документацию на видном месте, и то же самое работает для свойств и процедур, только мы убираем "Var" из атрибутов. Итак, измените наше общедоступное поле на доступное только для чтения свойство по умолчанию.

private pFooCount As Integer
Property Get FooCount() As Integer
Attribute FooCount.VB_Description = "Returns the number of Foos"
Attribute FooCount.VB_UserMemId = 0
FooCount = pFooCount
End Property

VB Object Browser and Attribute Description

Теперь, когда у нас есть объект Class1, он по умолчанию вернет FooCount.

Dim cls As New Class1
Dim i As Integer
i = cls
' is equivalent to
i = cls.FooCount

Когда вы можете захотеть так сделать? Ну, например, когда вы хотите создать строго типизированную коллекцию. Это подводит нас к последней детали. Есть еще одно специальное значение для VB_UserMemId, это значение -4. Отрицательное 4 всегда означает, что помечаемая функция должна возвращать перечислитель [_NewEnum]. Этот образец взят из приведенной выше ссылки на переполнение стека (исправлено, чтобы сделать Item членом класса по умолчанию).

Public Property Get Item(index As Long) As cShape
Attribute Item.VB_UserMemId = 0
 Set Item = myCustomCollection.Item(index)
End Property
Public Property Get NewEnum() As IUnknown
Attribute NewEnum.VB_UserMemId = -4
Attribute NewEnum.VB_MemberFlags = "40"
 Set NewEnum = myCustomCollection.[_NewEnum]
End Property

Ниже приводится сводка синтаксиса и значений.

' Header
Attribute VB_Name = "ClassOrModuleName"
Attribute VB_GlobalNameSpace = False ' ignored
Attribute VB_Creatable = False ' ignored
Attribute VB_PredeclaredId = False ' a Value of True creates a default global instance
Attribute VB_Exposed = True ' Controls how the class can be instanced.
'Module Scoped Variables
Attribute variableName.VB_VarUserMemId = 0 ' Zero indicates that this is the default member of the class.
Attribute variableName.VB_VarDescription = "some string" ' Adds the text to the Object Browser information for this variable.
 'Procedures
Attribute procName.VB_Description = "some string" ' Adds the text to the Object Browser information for the procedure.
Attribute procName.VB_UserMemId = someInteger
 ' 0: Makes the function the default member of the class.
 ' -4: Specifies that the function returns an Enumerator.

Обратите внимание, что в любом классе может быть только один член по умолчанию. У вас не может быть одновременно переменной-члена по умолчанию и процедуры по умолчанию.

Добавить комментарий