Использование предварительно объявленных классов в VBA в качестве пространств имен - PullRequest
5 голосов
/ 20 марта 2019

Одна из моих самых больших проблем с кодированием в VBA - это полное отсутствие пространств имен, затрудняющее обеспечение таких вещей, как определение области действия и выбор правильной функции, когда каждая функция с тем же именем находится в глобальном пространстве имен. Я знаю, что вы можете добавлять префиксы к вызовам функций с помощью имени модуля, в котором он находится, но мне кажется, что это также возможно путем замены всех ваших модулей на предварительно объявленные классы. Пространство имен будет выглядеть примерно так:

VERSION 1.0 CLASS
BEGIN
  MultiUse = -1  'True
END
Attribute VB_Name = "MyNamespace"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = False
'@Folder("Project.Namespace")
Option Explicit

Public Function Foo() As String
    Foo = "bar"
End Function

' Opionally make sure users do not use this as a class
Private Sub Class_Initialize()
    If Not Me Is MyNamespace Then
        Err.Raise 512, _
            Source:="MyNamespace.Initialize", _
            Description:="Cannot create an instance of a namespace."
    End If
End Sub

Таким образом, если вы когда-нибудь захотите позвонить Foo в это пространство имен, вы должны написать

MyNamespace.Foo()

Хотя простой вызов Foo() не сработает.

Мой вопрос такой:

Есть ли причина, по которой вы не хотели бы этого делать? Насколько я вижу, конструктор класса вызывается только при первом вызове любой из его функций после открытия проекта, поэтому я не вижу никаких накладных расходов, но может быть что-то подлое, о котором я не знаю. Конечно, это ни в коем случае не идеальный способ справиться с этим недостатком функциональности, но это не так, как если бы программисты VBA еще не использовали язык обходными путями, чтобы обеспечить отсутствие функциональности.

Кроме того, я вижу, что это в основном то же самое, что и этот вопрос, однако я также хотел бы знать, есть ли какие-либо конкретные проблемы с наличием в вашем коде тонны предварительно объявленных «пустых» классов , Допустим, вы замените 100 модулей на 100 предварительно объявленных классов, что окажет существенное влияние, например, на производительность / стабильность / и т.д ...?

1 Ответ

2 голосов
/ 20 марта 2019

Это стоит вам указатель объекта, это все.Я бы не назвал это пространством имен .

Каждый отдельный модуль UserForm, с которым вы когда-либо работали, имеет атрибут VB_PredeclaredId, установленный на True.Этот экземпляр автоматически создается, как вы заметили, и, хотя вы можете явно уничтожить его, в следующий раз, когда на него будут ссылаться, он будет автоматически (без вывода сообщений) заново создан ... с любым исходным состоянием / было ... довольноочень похоже на объект с автоматическим созданием, то есть объявление As New.

Так что то, что у вас есть, больше похоже на иерархию объектов, чем на структуру пространства имен - очень, очень похоже на то, как вы можете развернуть объект Excelмодель, начинающаяся с Application, и перейдите к следующему:

Set someCell = Excel.Application.Workbooks(1).Worksheets(1).Range("A1")

Здесь «пространство имен» - это библиотека Excel, Application - корневой объект, а остальная часть этого выражения - членaccess - свойства get, названные в честь классов.

Но классы не находятся в "пространствах имен" ... Worksheets collection type (class) существует сам по себе, подБиблиотека Excel: свойство Worksheets класса Application никоим образом не формирует и не защищает класс от "конфликта имен": если ваш пользовательский код имеет имя модуля классаd Worksheets (и это вполне возможно), а затем в соответствии с тем, как VBA разрешает ссылки на идентификаторы, Dim foo As Worksheet будет экземпляром этого пользовательского класса: единственным допустимым квалификатором является имя библиотеки (Excel, или MyVBAProject).

Итак, у вас есть разумный подход для построения относительно сложной структуры объектной модели - но он не будет (не может) заменять или имитировать пространство имен,Если вы обнаружите, что создаете «пустые» классы, пересмотрите свой дизайн.

Что касается последнего вопроса, я не вижу, как наличие 100 предварительно объявленных пользовательских объектов может отличаться от проекта с 100 пользовательскими формами: в обоихя хотел бы знать, есть ли способ обрезать это и обобщать / повторно использовать компоненты, будь то формы или классы.

То, чего вы хотите избежать, - это предварительно объявленный объект, который содержит состояние - потому чтотеперь это состояние действительно глобально, и вы не можете контролировать, что может изменить это состояние, где и когда: Application.Calculation является ярким примером этого.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...