Классовые (статические) методы в VBA - PullRequest
39 голосов
/ 28 декабря 2008

Интересно, можно ли создавать классы-методы в VBA. Под методом класса я подразумеваю методы, которые можно вызывать, не имея объекта класса. Ключевое слово «static» делает это в C ++ и Java.

В приведенном ниже примере я пытаюсь создать статический метод фабрики.

Пример:

'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'

Ответы [ 8 ]

40 голосов
/ 16 ноября 2010

1. Создайте нормальный класс, содержащий открытый (ые) метод (ы), который должен быть «статическим»

2. Включите открытый метод [в этот «статический» класс], который инициализирует [частные] «статические поля» внутри класса (он может принимать параметры, если хотите)

3. Создание модуля действует как фабрика

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. теперь вы можете использовать «статический» класс, вызывая CreateStaticClass («параметры»). MethodName («параметры») нет необходимости инициализировать экземпляр, как это делается методом фабрики

5. (Необязательно) Если вы хотите принудительно применить одноэлементные экземпляры, вы можете создать модуль, который действует как одноэлементный контейнер - включите частную переменную экземпляра и открытое свойство средства доступа. при желании вы можете использовать установщик let, чтобы позволить «заменять» синглтон новым [статическим] классом (используя другие параметры конструктора - см. # 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. Чтобы назначить синглтон:

CurrentStaticClass = CreateStaticClass(parameters)

7. Для использования синглтона:

[value = ] CurrentStaticClass.MethodName(parameters)
30 голосов
/ 28 декабря 2008

Это ("Public Shared") будет работать только в VB.Net.

Нет способа определить методы класса в VBA (или VB). Я бы предложил создать публичную функцию в модуле.

17 голосов
/ 04 июля 2014

Вы можете попробовать установить атрибут VB_PredeclaredId класса, для которого вы хотите быть статическим, равным True. Это создает экземпляр класса по умолчанию почти так же, как формы работают в VBA (обратите внимание, что вы можете ссылаться на них напрямую, не создавая экземпляр. Я знаю, что это не лучшая практика, но возможно).

Это означает, что у вас будет больше классов в стиле синглтона, но он может удовлетворить ваши требования ...

Вы не можете установить это непосредственно из самой IDE VBA, однако вы можете выполнить следующие шаги:

1. Экспортируйте класс, который вы хотите сделать статическим, в папку.

2. Откройте файл .cls, который вы экспортировали, в своем любимом текстовом редакторе и измените запись для VB_PredeclaredId, чтобы она читалась как VB_PredeclaredId = True.

3. Сохраните файл и повторно импортируйте в VBA.

После этого вы сможете вызывать ваши открытые методы в классе, не создавая экземпляр класса. Помните, что метод Initialize вызывается только в первый раз, когда вы выполняете метод класса / обращаетесь к свойству класса, а метод Terminate никогда не вызывается. Поэтому вы можете написать свой собственный конструктор, а также убедиться, что явно вызываете деструктор, если он вам нужен.

Ссылка: Пример UtterAccess.com Singleton

Ссылка: http://msdn.microsoft.com/en-us/library/ee199159.aspx

8 голосов
/ 27 августа 2009

Немного поздно, но какого черта

В 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, назначает параметры через установщики свойств и затем возвращает экземпляр. Если вы создаете экземпляры объектов во многих местах, это может сэкономить много кода.

4 голосов
/ 28 декабря 2008

AFAIK, самое близкое, что вы можете получить (и это не так близко), это использовать «анонимный» экземпляр, так что-то вроде этого:

With New NotReallyStaticClass
    .PerformNotReallyStatic Method, OnSome, Values
End With
2 голосов
/ 08 сентября 2011

Хотя это не совсем ответ на сам вопрос, я хотел бы отметить, что решения Майка Вудхауса следует избегать. Каждый раз создание нового экземпляра объекта - это снижение производительности, и оно действительно не решает исходную проблему - оно не создает статический объект и не предоставляет статические методы.

Поскольку в VBA нет понятия функций класса, самое близкое, что можно получить - это использование функций в модулях.

Что касается фабричных методов, я предлагаю создать модуль со словом Factory, добавленным к имени класса, который создает модуль. Что-то вроде:

'Module PersonFactory
Option Explicit

Public Function Create(ByVal sName As String) As Person

    'Code here

End Function

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

1 голос
/ 07 декабря 2011

Свойство 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, «Свойство экземпляра»)):

GlobalMultiUse. Подобно MultiUse, с одним дополнением: свойства и методы класса могут вызываться так, как если бы они были просто глобальными функциями. Нет необходимости сначала явно создавать экземпляр класса, потому что он будет создан автоматически.

0 голосов
/ 19 февраля 2009

Вы должны объявить p2, прежде чем сможете использовать Набор следующим образом:

дим р2 как персона

Как только вы это сделаете, вы должны заменить оператор Set, используя стандартное присваивание: p2 = Person.Create ("Bob")

В функции: удалите ключевое слово "Set" ... это также может быть источником ошибки.

Я летаю вслепую, но логически кажется, что это должно сработать. Я новичок в использовании модулей класса в VBA, но они не слишком отличаются от использования свойств VB.Net.

...