22

VB6 classes have no parameterized constructors. What solution have you chosen for this? Using factory methods seems like the obvious choice, but surprise me!

StayOnTarget
  • 11,743
  • 10
  • 52
  • 81
Dabblernl
  • 15,831
  • 18
  • 96
  • 148
  • 9
    Lack of constructors is not a good way to say it IMO. VB6 *does* indeed have parameterless constructors (`Class_Initialize` method). What it doesn't have is parameterized constructors. – Mehrdad Afshari Aug 01 '10 at 17:11

4 Answers4

6

How about using the available class initializer? This behaves like a parameterless constructor:

Private Sub Class_Initialize()
    ' do initialization here

End Sub
Dirk Vollmar
  • 172,527
  • 53
  • 255
  • 316
  • 3
    The fact that it doesn't accept any parameters makes it pretty useless as a constructor. It really only lets you set up a few things, but not truly initialize the object's state. – derekerdmann Aug 01 '10 at 17:13
  • 1
    Sorry, my question was unclear. I meant how to solve the problem that there is only a parameterless constructor: Class_Initialize – Dabblernl Aug 01 '10 at 20:58
  • The question was changed after this answer was posted. – StayOnTarget Oct 05 '18 at 19:50
6

I usually stick to factory methods, where I put the "constructors" for related classes in the same module (.BAS extension). Sadly, this is far from optimal since you can't really limit access to the normal object creation in VB6 - you just have to make a point of only creating your objects through the factory.

What makes it worse is having to jump between the actual object and your factory method, since organization in the IDE itself is cumbersome at best.

StayOnTarget
  • 11,743
  • 10
  • 52
  • 81
derekerdmann
  • 17,696
  • 11
  • 76
  • 110
  • Or what about adding the factory method to the class itself? Putting the factory methods in a module makes them application specific. – Dabblernl Aug 01 '10 at 21:00
  • @Dabblernl - But then you'd have to make them the equivalent of Java's `public static`, right? VB6 doesn't have static methods. – derekerdmann Aug 01 '10 at 21:55
  • Well, no need for a static class. You would have to create an instance to access the factory method, but as you do not make use of the object's dependencies that would be acceptable IMHO – Dabblernl Aug 01 '10 at 22:23
  • @Dabblernl - Ah, I see. That actually sounds like a better solution, I'll have to try it out. – derekerdmann Aug 01 '10 at 23:25
  • 4
    +1. It's worth mentioning a special case. If your class is defined in another component (e.g. ActiveX DLL), you can limit access to normal object creation. Make the class PublicNotCreatable which forces the client to use your factory method. http://msdn.microsoft.com/en-us/library/aa242107(VS.60).aspx – MarkJ Aug 02 '10 at 09:02
  • @Dabblernl But if you're going to use a non static factory function in a "dummy" instance, why not just use an `Init()` method that you'd do your normal initialisation in? – Deanna Feb 28 '13 at 10:21
5

I use a mix of factory functions (in parent classes) that then create an instance of the object and call a Friend Init() method.

Class CObjects:

Public Function Add(ByVal Param1 As String, ByVal Param2 As Long) As CObject
  Dim Obj As CObject
  Set Obj = New CObject
  Obj.Init Param1, Param2
  Set Add = Obj
End Function

Class CObject:

Friend Sub Init(ByVal Param1 As String, ByVal Param2 As Long)
  If Param1 = "" Then Err.Raise 123, , "Param1 not set"
  If Param2 < 0 Or Param2 > 15 Then Err.Raise 124, , "Param2 out of range"

  'Init object state here
End Sub

I know the Friend scope won't have any effect in the project, but it acts as a warning that this is for internal use only. If these objects are exposed via COM then the Init method can't be called, and setting the class to PublicNotCreatable stops it being created.

Community
  • 1
  • 1
Deanna
  • 23,876
  • 7
  • 71
  • 156
0

This solution is far from perfect, however, this is what I ended up doing for some of my legacy projects. It's somewhat memory-efficient for storage, but just looking up something definitely takes more time than otherwise required, especially for the huge structs.

Suppose you need to implement the following,

type user
 id as long
 name as String
 desc as String
end type

But notice that VB6 natively supports Strings. So Instead of using structs, have "fake-struct" functions such as

Public Function user_raw(ByVal id as Long, ByRef name as String, ByRef desc as String) as String
 Const RAW_DELIM as String = "|"
 user_raw = cstr(id) & RAW_DELIM & name & RAW_DELIM & desc 
End Function

So as a result, you will have passable-by-value (hence stackable into arrays, or multiline Strings), "fake-structs" made of strings such as

1|Foo|The boss of VB

2|Bar|Foo's apprentice

So the construct also counts as a crude way to perform to_string(). On the slightly good side, such storage is almost instantly convertible to the Markdown table syntax.

Later on, you can retrieve data from the struct by doing something like,

Public const RAW_DELIM as String = "|"
Public Const POS_USER_ID = 0
Public Const POS_USER_NAME = 1
Public Const POS_USER_DESC = 2
'...
public function get_raw_variable(byref user as String, byval var as integer) as String
 dim buf() as String

 buf = SPLIT(user, "|")
 Assert ubound(buf) <= var
 get_raw_variable = buf(var)
end function

The retrieval is sure inefficient, but is about the best you can have. Good luck

TAbdiukov
  • 1,185
  • 3
  • 12
  • 25