0

I’m creating a set of User Defined Classes using Implements. Some (but not all) of the Properties and Methods of the implemented classes use exactly the same code in each implemented class. What I would like to do is move that code to one place, to avoid repeating myself.

An minimal example to demonstrate the requirement:

Class cMasterClass

Option Explicit

Private pMyClasses As Collection

Public Property Get Item(idx As Long)
    Set Item = pMyClasses.Item(idx)
End Property

Public Property Get SomeProperty() As String
    SomeProperty = "Master Class"
End Property

Public Sub AddClass(Name As String, Instance As Long)
    Dim NewClass As cTemplateClass
    Select Case Instance
        Case 1
            Set NewClass = New cMyClass1
        Case 2
            Set NewClass = New cMyClass2
    End Select
    NewClass.Init Me, Name
    pMyClasses.Add NewClass, Name
    
End Sub


Private Sub Class_Initialize()
    Set pMyClasses = New Collection
End Sub

Class cTemplateClass

Option Explicit


Public Property Get Name() As String: End Property

Public Property Get Parent() As cMasterClass: End Property

Public Property Get SomeProperty() As String: End Property

Public Sub Init(Parent As cMasterClass, Name As String): End Sub

Class cMyClass1

Option Explicit

Implements cTemplateClass

Private pParent As cMasterClass
Private pName As String

Public Property Get cTemplateClass_Name() As String: cTemplateClass_Name = pName: End Property

Public Property Get cTemplateClass_Parent() As cMasterClass: Set cTemplateClass_Parent = pParent: End Property

Public Property Get cTemplateClass_SomeProperty() As String
    cTemplateClass_SomeProperty = "Some String from MyClass 1"
End Property

Public Sub cTemplateClass_Init(Parent As cMasterClass, Name As String)
    Set pParent = Parent
    pName = Name
End Sub

Class cMyClass2

Option Explicit

Implements cTemplateClass

Private pParent As cMasterClass
Private pName As String

Public Property Get cTemplateClass_Name() As String: cTemplateClass_Name = pName: End Property

Public Property Get cTemplateClass_Parent() As cMasterClass: Set cTemplateClass_Parent = pParent: End Property

Public Property Get cTemplateClass_SomeProperty() As String
    cTemplateClass_SomeProperty = "Some String from MyClass 2"
End Property

Public Sub cTemplateClass_Init(Parent As cMasterClass, Name As String)
    Set pParent = Parent
    pName = Name
End Sub

Standard Module

Sub Demo()
    Dim MyMasterClass As cMasterClass
    Set MyMasterClass = New cMasterClass
    
    MyMasterClass.AddClass "Example class 1", 1
    MyMasterClass.AddClass "Example class 2", 2
    
    Dim SomeInstance As cTemplateClass
    Set SomeInstance = MyMasterClass.Item(1)
    Debug.Print "Instance 1", SomeInstance.Name, "Parent", SomeInstance.Parent.SomeProperty
    
    Set SomeInstance = MyMasterClass.Item(2)
    Debug.Print "Instance 2", SomeInstance.Name, "Parent", SomeInstance.Parent.SomeProperty
End Sub

Notice that in cMyClass1 and cMyClass2 the code for Init, Name and Parent are identical (but SomeProperty is not)

How could I move the common code from the individual classes into one place (I know the Template class cannot contain the common code)?

braX
  • 11,506
  • 5
  • 20
  • 33
chris neilsen
  • 52,446
  • 10
  • 84
  • 123
  • I now realise that what I am asking for here is Inheritance, which VBA does not directly support. The linked dup nicely explains taht, and offers an alternative – chris neilsen Oct 15 '22 at 21:59

1 Answers1

1

How could I move the common code from the individual classes into one place (I know the Template class cannot contain the common code)?

Hi Chris, actually the Template class can contain that common code and be used with Implements to ensure that interface implementation. I am late with this answer and I am not sure if this can help you but anyway ... :). What you could consider would be to actually move the parent and name to your template class and use init to fill them and at the same time with using implements create instance of the template so your classes ensure that interface and they can redirect the code to the template at the same time. If you wish have a look here for another example. HTH, Dan

Change the child classes a bit:

Option Explicit

Implements cTemplateClass

'Move this to your template class:
'Private pParent As cMasterClass
'Private pName As String

'and declare the varaible of template class here instead:
Private pTemplate As cTemplateClass

Public Property Get cTemplateClass_Name() As String
    'Redirect the property to template class instance
    'cTemplateClass_Name = pName
    cTemplateClass_Name = pTemplate.Name
End Property

Public Property Get cTemplateClass_Parent() As cMasterClass
    'Redirect the property to template class instance
    'Set cTemplateClass_Parent = pParent
    Set cTemplateClass_Parent = pTemplate.Parent
End Property

Public Sub cTemplateClass_Init(Parent As cMasterClass, Name As String)
' Instantiate here the template class and redirect the Init
'    Set pParent = Parent
'    pName = Name

    Set pTemplate = New cTemplateClass
    pTemplate.Init Parent, Name
End Sub

Public Property Get cTemplateClass_SomeProperty() As String
    cTemplateClass_SomeProperty = "Some String from MyClass 2"
End Property

And anhance the template class a bit too:

Option Explicit

'Move this here from your 'derived' classes:
Private pParent As cMasterClass
Private pName As String

Public Property Get Name() As String
    Name = pName
End Property

Public Property Get Parent() As cMasterClass
    Set Parent = pParent
End Property

Public Sub Init(Parent As cMasterClass, Name As String)
    Set pParent = Parent
    pName = Name
End Sub

Public Property Get SomeProperty() As String
End Property
Daniel Dušek
  • 13,683
  • 5
  • 36
  • 51
  • Thank you Daniel for this. It confirms what I thought: it confirms what I thought - that I have to have code stubs that redirect the code to a common location. I also now realise what I was asking for is Inheritance, which VBA does not directly support. – chris neilsen Oct 15 '22 at 21:58
  • Yes in vba there is no class inheritance so you need to do some extra work to redirect calls to a common location, e.g. in another class like here or in other common place in general. – Daniel Dušek Oct 17 '22 at 11:30