Méthodes de classe (statiques) dans VBA

Je me demande s'il est possible de créer des méthodes de classe dans VBA. Par méthode de classe, je veux dire des méthodes qui peuvent être appelées sans avoir d'objet de la classe. Le mot-clé'static' 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'
37
demandé sur Renaud Bompuis 2008-12-28 15:03:38

8 réponses

That ("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
répondu John Saunders 2011-12-07 01:50:08

1. créez une classe normale contenant la ou les méthodes publiques dont vous avez besoin pour être 'static'

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

3. 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 ('paramètres') il n'est pas nécessaire de l'initialiser l'instance comme cela est fait par la méthode de

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 public. en option, vous pouvez utiliser un setter ' let 'pour permettre au singleton d'être 'remplacé' par une nouvelle classe [static] (en utilisant différents paramètres du constructeur-voir # 2,3). Utilisez ' Let 'pour le setter, de sorte que vous pouvez assigner le singleton sans utiliser' set ' ala Langues OO

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.{[6] } pour attribuer le singleton:

CurrentStaticClass = CreateStaticClass(parameters)

7. Pour utiliser le singleton:

[value = ] CurrentStaticClass.MethodName(parameters)
37
répondu Matthew Paul Arnold 2012-03-31 11:05:18

Vous pouvez essayer de définir l'attribut VB_PredeclaredId de la classe que vous souhaitez être statique sur True. Cela crée une instance par défaut de la classe de la même manière que les formes 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 le plus 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 de L'IDE VBA lui-même, toutefois, vous pouvez effectuer les étapes suivantes:

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

2. ouvrez le fichier .cls que vous avez exporté dans votre éditeur de texte préféré et entrée pour VB_PredeclaredId afin qu'il lit 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 est seulement appelée la première fois que vous exécutez une méthode de classe / accédez à une propriété de classe, et la méthode Terminate n'est jamais appelée. Par conséquent, vous pouvez écrire votre propre constructeur et également vous assurer d'appeler explicitement le destructeur si vous en avez besoin.

Référence: UtterAccess.com Exemple Singleton

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

12
répondu i_saw_drones 2017-07-01 16:27:27

Un peu tard dans la journée mais que diable

Il n'y a pas de classe ou de méthodes statiques dans VB6/VBA. Mais vous pouvez explicitement 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 setter de propriété mais ce n'est pas le point Je suis en train de faire. EmployeeUtil est essentiellement un titulaire de place pour les membres non-instance.

Vous noterez que la méthode Create de cette façon nous donne un constructeur pseudo comme 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 setters de propriétés, puis de renvoyer l'instance. Si vous construisez des instances d'objets dans beaucoup d'endroits, cela peut économiser beaucoup de code.

7
répondu Swanny 2009-08-27 05:15:16

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
répondu Mike Woodhouse 2008-12-28 16:29:23

Instanciation propriété d'une classe similaire est disponible pour une utilisation dans les classes statiques. La propriété d'instanciation 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

GlobalMultiUse instanciation propriété pour spécifier la classe comme un ensemble de...

Exemple d'utilisation de ce mondial (statique!) classe dans un autre projet standart 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

Enfin, les notes dans MSDN ((bibliothèque MSDN Visual Studio 6.0, 'Instancing Property')):

GlobalMultiUse. Semblable à MultiUse, avec un ajout: les propriétés et les 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 en premier, car une instance sera automatiquement créée.

2
répondu fuat aygan 2011-12-07 19:19:35

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

Puisque VBA n'a pas de concept de fonctions de classe, le plus proche peut obtenir utilise des fonctions dans les modules.

Comme pour usine méthodes, je suggère création d'un module avec le mot 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

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

1
répondu xxbbcc 2011-09-08 03:59:41

Vous devez déclarer p2 avant de pouvoir utiliser l'Ensemble comme suit:

Dim p2 en tant que personne

Une fois que vous faites cela, vous devez remplacer L'Instruction Set en utilisant une affectation standard: p2 = personne.Créer ("Bob")

Dans la fonction: supprimez le mot clé" Set"...cela pourrait aussi être la source d'une erreur.

Je vole à l'aveugle, mais logiquement, il semble que cela devrait fonctionner. Je suis nouveau à utiliser des modules de classe dans VBA mais ils ne sont pas trop différents de l'utilisation VB.Net propriétés.

-1
répondu 2009-02-19 12:12:45