web-dev-qa-db-fra.com

Méthodes de classe (statiques) dans VBA

Je me demande s'il est possible de créer des méthodes de classe en VBA. Par méthode de classe, j'entends des méthodes qui peuvent être appelées sans avoir d'objet de la classe. Le mot-clé 'statique' fait cette astuce en C++ et Java.

Dans l'exemple ci-dessous, j'essaie de créer une méthode d'usine statique.

Exemple:

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

Cela ("Public Shared") ne fonctionnerait que dans VB.Net.

Il n'y a aucun moyen de définir des méthodes de classe dans VBA (ou VB). Je suggère de créer une fonction publique dans un module.

30
Thomas

1. Créez une classe normale contenant la ou les méthodes publiques dont vous avez besoin d'être 'statique'

2. Inclure une méthode publique [dans cette classe "statique"] qui initialise les "champs statiques" [privés] dans la classe (elle peut prendre des paramètres si vous le souhaitez)

. Créer un module agit comme une usine

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. vous pouvez maintenant utiliser la classe 'static' en appelant CreateStaticClass ('parameters'). MethodName ('parameters') il n'est pas nécessaire d'initialiser l'instance comme cela est fait par la méthode d'usine

5. (Facultatif) Si vous souhaitez appliquer des instances singleton, vous pouvez créer un module qui agit comme un conteneur singleton - inclure une variable d'instance privée et une propriété d'accesseur publique. vous pouvez éventuellement utiliser un setter "let" pour permettre au singleton d'être "remplacé" par une nouvelle classe [statique] (en utilisant différents paramètres de constructeur - voir # 2,3). Utilisez 'Let' pour le setter, ainsi vous pouvez assigner le singleton sans utiliser '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. Pour affecter le singleton:

CurrentStaticClass = CreateStaticClass(parameters)

7. Pour utiliser le singleton:

[value = ] CurrentStaticClass.MethodName(parameters)
41

Vous pouvez essayer de définir le VB_PredeclaredId attribut de la classe à laquelle vous souhaitez être statique à True. Cela crée une instance par défaut de la classe de la même manière que les formulaires fonctionnent dans VBA (notez que vous pouvez vous y référer directement sans créer d'instance. Je sais que ce n'est pas la meilleure pratique mais c'est possible).

Cela signifie que vous auriez plus d'une classe de style singleton, mais cela pourrait répondre à vos besoins ...

Vous ne pouvez pas définir cela directement à partir du VBA IDE lui-même, cependant, vous pouvez effectuer les étapes suivantes:

1. Exportez la classe que vous souhaitez rendre statique dans un dossier.

2. Ouvrez le .cls fichier que vous avez exporté dans votre éditeur de texte préféré et modifiez l'entrée pour VB_PredeclaredId pour qu'il indique VB_PredeclaredId = True.

3. Enregistrez le fichier et réimportez-le dans VBA.

Vous devriez alors pouvoir appeler vos méthodes publiques sur la classe sans avoir à instancier la classe. Gardez à l'esprit que la méthode Initialize n'est appelée que la première fois que vous exécutez une méthode de classe/accédez à une propriété de classe et que la méthode Terminate n'est jamais appelée. Par conséquent, vous souhaiterez peut-être écrire votre propre constructeur et vous assurer également d'appeler explicitement le destructeur si vous en avez besoin.

Référence: Exemple Singleton UtterAccess.com

Référence: http://msdn.Microsoft.com/en-us/library/ee199159.aspx

18
i_saw_drones

Un peu tard dans la journée mais bon sang

Il n'y a aucune classe ou méthode statique dans VB6/VBA. Mais vous pouvez explicitement indiquer le nom d'un module. Vous ne pouvez pas avoir un module et une classe du même nom, mais vous pouvez l'appeler quelque chose de similaire.

Donc, je pourrais avoir une classe appelée Employee et un module appelé EmployeeUtil et ensuite je peux écrire:

  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

Oui, les valeurs sont codées en dur et la gestion du code devrait probablement être sous le configurateur de propriétés, mais ce n'est pas le point que j'essaie de faire. EmployeeUtil est essentiellement un espace réservé pour les membres non-instance.

Vous remarquerez que la méthode Create de cette façon nous donne un pseudo-constructeur similaire pour la classe Employee. Tout ce que cette fonction fait est de créer une instance de Employee, d'affecter les paramètres via les paramètres de propriété, puis de renvoyer l'instance. Si vous construisez des instances d'objets dans de nombreux endroits, cela peut économiser beaucoup de code.

8
Swanny

AFAIK, le plus proche que vous pouvez obtenir (et ce n'est pas si proche) est d'utiliser une instance "anonyme", donc quelque chose comme ceci:

With New NotReallyStaticClass
    .PerformNotReallyStatic Method, OnSome, Values
End With
4
Mike Woodhouse

Bien que ce ne soit pas strictement une réponse à la question elle-même, je voudrais souligner que la solution de Mike Woodhouse doit être évitée. Chaque fois que créer une nouvelle instance d'un objet est un problème de performance et cela ne résout pas vraiment le problème d'origine - il ne crée pas d'objet statique et il ne fournit pas non plus de méthodes statiques.

Puisque VBA n'a pas de concept de fonctions de classe, le plus proche peut être d'utiliser des fonctions dans des modules.

En ce qui concerne les méthodes d'usine, je suggère de créer un module avec Word Factory ajouté au nom de la classe que le module crée. Quelque chose comme:

'Module PersonFactory
Option Explicit

Public Function Create(ByVal sName As String) As Person

    'Code here

End Function

Ceci est loin du concept de méthode statique d'autres langages mais au moins il fournit un modèle qui peut être utilisé dans un projet.

2
xxbbcc

La propriété d'instanciation d'une classe similaire est disponible pour une utilisation dans les classes statiques. La propriété d'instance pour elle 'GlobalMultUse' doit spécifier.

Exemple de classe statique:

' 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

Propriété Instance GlobalMultiUse pour spécifier la classe comme un ensemble de ...

Exemple d'utilisation de cette classe globale (statique!) Dans un autre projet EXE standard:

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

Enfin, des notes dans MSDN ((MSDN Library Visual Studio 6.0, 'Instancing Property')):

GlobalMultiUse. Similaire à MultiUse, avec un ajout: les propriétés et méthodes de la classe peuvent être invoquées comme s'il s'agissait simplement de fonctions globales. Il n'est pas nécessaire de créer explicitement une instance de la classe d'abord, car une sera automatiquement créée.

1
fuat aygan