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