English 中文(简体)
Is there a way to overload the constructor / initialize procedure for a class in VBA?
原标题:

In C#, I know that I can overload the constructor for a class by specifying it in the body of the class:

public class MyClass()
{
    public MyClass(String s) { ... }
}

This overrides the default constructor (which has no parameters) and forces the class to be initialized with parameter s.

I know that in VBA I can initialize my class with Private Sub Class_Initialize(), but I don t know if there s a way to force my class to be initialized with parameters. Can this be done?

最佳回答

As Jtolle indicated, this is simply not possible in VBA/VB6. There is no perfect way to work around this but, what I personally do is create a Public/Friend sub call Initialize with the parameters I want (in VBA/VB6 you use "Optional" parameters for overloading) and then put a quick check in all exposed members of the class that throws an exception if you try to access them without running the initialize method. A basic example might look like this:

Option Explicit

Private m_blnInitialized As Boolean
Private m_lngID As Long
Private m_strFirstName As String

Public Sub Initialize(ByVal ID As Long, Optional ByVal someOtherThing As String = vbNullString)
    If m_blnInitialized Then Me.Clear
    m_lngID = ID
    m_strFirstName = SomeLookUp()
    If LenB(someOtherThing) Then
          Do something here.
    End If
    m_blnInitialized = True
End Sub

Public Property Get ID() As Long
    If Not m_blnInitialized Then Err.Raise eStandardErrors.eNotInitialized
    ID = m_lngID
End Property

Public Property Get FirstName() As String
    If Not m_blnInitialized Then Err.Raise eStandardErrors.eNotInitialized
    FirstName = m_strFirstName
End Property

Private Function SomeLookUp() As String
      perform magic on Me.ID
End Function

Public Sub LoadPicture()
    If Not m_blnInitialized Then Err.Raise eStandardErrors.eNotInitialized
      More magic
End Sub

Public Sub Clear()
    If Not m_blnInitialized Then Err.Raise eStandardErrors.eNotInitialized
    m_strFirstName = vbNullString
    m_lngID = 0&
    m_blnInitialized = False
End Sub

It s not great, but it s about as good as it s going to get with VBA/VB6.

问题回答

You already have two correct answers; you can t literally have a constructor with parameters in VBA.

Oorang s workaround is basically right - have a separate "init" method. When I do take an object-oriented approach to something in Excel/VBA, I prefer to hide both object creation and init in a regular function. So I d have mkFoo(parm) and call it to get a Foo instance. mkFoo() would create a New Foo instance and call Foo.init(). If you only ever create instances that way, you don t need to check if your instance has been initialized over and over again.

If you re really trying to be correct and not supply an object with a maybe-now-dangerous init() method exposed, you can have an IFoo interface (with no init method) that is implemented by Foo. Then mkFoo() returns an IFoo, and any users of the actual Foo never see the init() method at all.

Of course, now you have a bunch of modules just for Foo - one for IFoo, one for each actual Foo class, and one for your "Foo factory" function...thus my comment that this is one of many reasons why OOP in VBA is a PITA, even if it is useful sometimes.

EDIT: This was an edit by onedaywhen from shortly after the original answer, but I pulled it out separately just now since it is really a separate thought:

Speaking of Excel, you could relocate the Foo class into a .xla add-in and make the class PublicNotCreateable. The Public Function mkFoo(parm) could reside in a standard .bas module in the add-in and therefore called a bit like a static class in C#. This forces client code to use mkFoo as the only way of creating a Foo instance. No doubt there is a MS Access analogy to Excel s .xla add-ins.

No, classes cannot be initialized with parameters in VBA. This wouldn t be legal because of the Dim ... As New ... statement, which implicitly constructs objects when they re first accessed.

Dim x As New MyClass

x.Prop = 42   Before x.Prop is set, x is implicitly constructed

Class Constructor Methods and overloading the Class constructor In Visual Basic 6.0, the class Initialize event handler named Class_Initialize is used to execute code that needs to be executed at the moment that an object is created.

In Visual Basic 2005, one or more constructors are added to a class to execute code and initialize variables. Constructors are the methods in a class that are named New. The New method can be overloaded to provide multiple constructors with the name New within the same class statement.

For more information, see New (Visual Basic) or Using Constructors and Destructors. http://msdn.microsoft.com/en-us/library/55yzhfb2(v=vs.80).aspx





相关问题
Anyone feel like passing it forward?

I m the only developer in my company, and am getting along well as an autodidact, but I know I m missing out on the education one gets from working with and having code reviewed by more senior devs. ...

NSArray s, Primitive types and Boxing Oh My!

I m pretty new to the Objective-C world and I have a long history with .net/C# so naturally I m inclined to use my C# wits. Now here s the question: I feel really inclined to create some type of ...

C# Marshal / Pinvoke CBitmap?

I cannot figure out how to marshal a C++ CBitmap to a C# Bitmap or Image class. My import looks like this: [DllImport(@"test.dll", CharSet = CharSet.Unicode)] public static extern IntPtr ...

How to Use Ghostscript DLL to convert PDF to PDF/A

How to user GhostScript DLL to convert PDF to PDF/A. I know I kind of have to call the exported function of gsdll32.dll whose name is gsapi_init_with_args, but how do i pass the right arguments? BTW, ...

Linqy no matchy

Maybe it s something I m doing wrong. I m just learning Linq because I m bored. And so far so good. I made a little program and it basically just outputs all matches (foreach) into a label control. ...

热门标签