Интересно, можно ли создавать класс-методы в VBA. По методу класса я имею в виду методы, которые могут быть вызваны без наличия объекта класса. "Статическое" ключевое слово делает этот трюк в С++ и Java.
В приведенном ниже примере я пытаюсь создать статический метод factory.
Пример:
'Classmodule Person'
Option Explicit
Private m_name As String
Public Property Let name(name As String)
m_name = name
End Property
Public Function sayHello() As String
Debug.Print "Hi, I am " & m_name & "!"
End Function
'---How to make the following method static?---'
Public Function Create(name As String) As Person
Dim p As New Person
p.m_name = name
Set Create = p
End Function
'Using Person'
Dim p As New Person
p.name = "Bob"
p.sayHello 'Works as expected'
Set p2 = Person.Create("Bob") 'Yields an error'
Это ( "Public Shared" ) будет работать только в VB.Net.
Невозможно определить методы класса в VBA (или VB). Я бы предложил создать публичную функцию в модуле.
1. Создайте нормальный класс, содержащий общедоступный метод (ы), который вам нужно статично
2. Включить общедоступный метод [в этот "статический" класс], который инициализирует [private] "статические поля" внутри класса (он может принимать параметры, если вы пожелаете)
3. Создание модуля действует как factory
Public Function CreateStaticClass(parameters for 'constructor') As StaticClass
Dim static As StaticClass
Set static = New StaticClass
Call StaticClass.Constructor(pass in parameters)
Set CreateStaticClass = static
End Function
4. теперь вы можете использовать класс "static", вызвав CreateStaticClass ( "параметры" ). MethodName ('parameters') нет необходимости инициализировать экземпляр так, как это делается с помощью метода factory
5. (Необязательно). Если вы хотите принудительно использовать экземпляры singleton, вы можете создать модуль, который будет действовать как контейнер singleton, - включить переменную частного экземпляра и свойство общедоступного доступа. возможно, вы можете использовать установщик 'let', чтобы позволить singleton "заменяться" новым [статическим] классом (используя разные параметры конструктора - см. № 2,3). Используйте "Let" для установщика, поэтому вы можете назначить синглтон без использования "set" ala OO languages
Private curStaticClass as StaticClass
Public Property Get CurrentStaticClass() As StaticClass
If curStaticClass Is Nothing Then Set curStaticClass = CreateStaticClass
Set CurrentStaticClass = curStaticClass
End Property
Public Property Let CurrentStaticClass(value As StaticClass)
If Not (curStaticClass Is Nothing) Then Set curStaticClass = Nothing
Set curStaticClass = value
End Property
6. Чтобы назначить singleton:
CurrentStaticClass = CreateStaticClass(parameters)
7. Чтобы использовать singleton:
[value = ] CurrentStaticClass.MethodName(parameters)
Вы можете попробовать установить атрибут VB_PredeclaredId
класса, который должен быть статичным, в True
. Это создает экземпляр класса по умолчанию во многом таким же образом, что формы работают в VBA (обратите внимание, что вы можете ссылаться на них напрямую, не создавая экземпляр. Я знаю, что это не лучшая практика, но это возможно).
Это означает, что у вас будет больше одноэлементного стиля, но он может служить вашим требованиям...
Вы не можете установить это непосредственно из самой VBA IDE, однако вы можете выполнить следующие шаги:
1. Экспортировать класс, который вы хотите сделать статичным в папку.
2. Откройте файл .cls
, который вы экспортировали в своем любимом текстовом редакторе, и измените введите VB_PredeclaredId
, чтобы он читал VB_PredeclaredId = True
.
3. Сохраните файл и повторно импортируйте его в VBA.
Затем вы можете вызвать свои общедоступные методы в классе, не создавая экземпляр класса. Имейте в виду, что метод Initialize
вызывается только при первом запуске метода класса/доступа к свойству класса, а метод Terminate
никогда не вызывается. Поэтому вы можете написать свой собственный конструктор, а также убедиться, что вы явно вызываете деструктор, если он вам нужен.
Ссылка: Пример Singleton в UtterAccess.com
Ссылка: http://msdn.microsoft.com/en-us/library/ee199159.aspx
Бит в конце дня, но что за черт
В VB6/VBA нет классов или статических методов. Но вы можете объяснять название модуля. У вас не может быть модуль и класс с тем же именем, но вы могли бы назвать его похожим.
Итак, я мог бы иметь класс под названием Employee и модуль под названием EmployeeUtil, а затем я могу написать:
Dim emp As Employee
Dim code As String
Set emp = EmployeeUtil.Create( "Smith", "John", 21-Feb-1988)
code = "123XY"
If EmployeeUtil.IsCodeValid( code) Then
emp.Code = code
Else
emp.Code = EmployeeUtil.DefaultCode
EndIf
Да, значения жестко закодированы, и обработка кода должна, вероятно, находиться под настройщиком свойств, но это не то, что я пытаюсь сделать. EmployeeUtil по существу является владельцем места для членов без экземпляра.
Вы заметите, что метод Create таким образом дает нам псевдоподобный конструктор для класса Employee. Вся эта функция создает экземпляр Employee, назначает параметры через средства определения свойств, а затем возвращает экземпляр. Если вы создаете экземпляры объектов во многих местах, это может сэкономить много кода.
AFAIK, ближайший вы можете получить (и это не так близко), чтобы использовать "анонимный" экземпляр, так что примерно так:
With New NotReallyStaticClass
.PerformNotReallyStatic Method, OnSome, Values
End With
Свойство экземпляра аналогичного класса доступно для использования в статических классах. Свойство Instancing для этого объекта "GlobalMultUse" должно указывать.
Пример статического класса:
' Error Class in ClassInstancing ActiveDLL project
Option Explicit
Private m_errorID As Integer
Private m_Description As String
Public Property Get ErrorID() As Integer
ErrorID = m_errorID
End Property
Public Property Let ErrorID(ByVal vNewValue As Integer)
m_errorID = vNewValue
End Property
Public Property Get Description() As string
Description = m_Description
End Property
Public Property Let Description(ByVal vNewValue As string)
m_Description = vNewValue
End Property
Public Function Error() As Error
Dim errorInstance As New ClassInstancing.Error
With errorInstance
.ErrorID = Me.ErrorID
.Description = Me.Description
End With
Set Error = errorInstance
End Function
Public Sub RaiseError(ByVal pErrorID As Integer, ByVal errorSource As String, ByVal errorDesc As String)
Err.Raise pErrorID, errorSource, errorDesc
End Sub
Public Sub ShowError()
MsgBox "Error ID: " & CStr(Me.ErrorID) & vbCrLf & _
"Desc: " & Me.Description
End Sub
Свойство GlobalMultiUse Instancing для указания класса как набора...
Пример использования этого глобального (статического!) класса в другом стандартном проекте EXE:
Private Sub Command1_Click()
ClassInstancing.Description = "Sample-1 error using !"
ClassInstancing.ErrorID = 9990
'Dim multiuseClass As ClassInstancing.Error
'Set multiuseClass = ClassInstancing.Error
MsgBox ClassInstancing.Error.ErrorID & vbCrLf & ClassInstancing.Error.Description, vbInformation, "Sample Usage 1"
ClassInstancing.Description = "Sample-2 error using !"
ClassInstancing.ErrorID = 1110
ClassInstancing.ShowError
End Sub
Наконец, заметки в MSDN ((библиотека MSDN Visual Studio 6.0, свойство Instancing)):
GlobalMultiUse. Подобно MultiUse, с одним добавлением: свойства и методы класса могут быть вызваны, как если бы они были просто глобальными функциями. Не обязательно явно создавать экземпляр класса, потому что он будет автоматически создан.
Хотя это не является строго ответом на вопрос, я хотел бы указать, что решение Майка Вудхауса следует избегать. Каждый раз, когда создание нового экземпляра объекта является хитом производительности, и он действительно не решает исходную проблему - он не создает статический объект и не предоставляет также статические методы.
Так как VBA не имеет понятия функций класса, то ближайшим из них может быть использование функций в модулях.
Что касается методов factory, я предлагаю создать модуль со словом factory, добавленным к имени класса, который создает модуль. Что-то вроде:
'Module PersonFactory
Option Explicit
Public Function Create(ByVal sName As String) As Person
'Code here
End Function
Это далеко не концепция статического метода для других языков, но по крайней мере она предоставляет шаблон, который можно использовать в проекте.
вам нужно объявить p2, прежде чем вы сможете использовать Set следующим образом:
dim p2 как Person
Как только вы это сделаете, вы должны заменить оператор Set, используя стандартное назначение: p2 = Person.Create( "Боб" )
В функции: удалите ключевое слово "Установить"... это также может быть источником ошибки.
Я летел слепой, но логически кажется, что это должно сработать. Я новичок в использовании модулей класса в VBA, но они не слишком отличаются от использования свойств VB.Net.