1

Trying to do inheritance in VBA I sometimes encounter the issue of having an instance of a child class and needing to call a function from the parent's class that the child overrides.

Quick example:

In IGreeter.cls

Public Sub Greet()
End Sub

In PoliteGreeter.cls

Implements IGreeter

Private Sub IGreeter_Greet()
  Debug.Print "Good morning"
End Sub

In Main.bas

Public Sub RunGreeter()

  Dim MyGreeter As PoliteGreeter
  Set MyGreeter = New PoliteGreeter

  MyGreeter.Greet ' Doesn't work, function not defined

End Sub

There are of course easy ways to solve the issue for this example, two ways I see are:

  1. Define MyGreeter as an instance of IGreeter instead.
  2. Make the override function public and call IGreeter_Greet directly.

Neither of these solutions are very good. For the first one, if I had additional functionality in PoliteGreeter that I wanted to access I would need two variables to accessed its full scope of functions. The second solution is both ugly and seems very very wrong, specially since VBE by default makes the definition private.

There is however a third solution that I see and that is to add Greet also as a public method of PoliteGreeter as following

Implements IGreeter

Public Sub Greet()
  IGreeter_Greet
End Sub

Private Sub IGreeter_Greet()
  Debug.Print "Good morning"
End Sub

A fourth solution would be to do the first one and solve my concern with additional functionality through composition instead as VBA doesn't actually do inheritance. However my question is whether this third method is safe, if it shadows something, if there are caveats, and if there are other better standard solutions to this kind of problem.

  • There is no inheritance in VBA. Use Composition instead... https://stackoverflow.com/a/31861832/10223558 Unfortunately there isn't really a better solution, the OOP-Capabilites of VBA are quite limited in this regard. You already pointed this out in your question, I'll leave the comment for the link. – L8n Sep 11 '19 at 08:32
  • 1
    The third solution is fine, but you'll loose the advantage of using an Interface and could just as well leave it out. – L8n Sep 11 '19 at 08:35
  • @L8n I guess my thinking is that in certain situations although VBA doesn't do OOP, if I was able to mimic it just enough I would get away with creating 1 class instead of 2, meaning that I would have less code to worry about and less things to name when composition doesn't really give me anything extra. Also, what do you mean I loose the advantage of using an Interface? I can still pass the object to anything that expects an `IGreeter` and use it like a regular interface. – Aleksandra Glesaaen Sep 11 '19 at 08:40
  • Since you will be refering to the child class directly you won't be able to exchange the object at runtime. If you want to reuse code (and only keep it in one place) you have to use composition. – L8n Sep 11 '19 at 08:47
  • That is a good point, I don't do much runtime polymorphism, I mostly use it for code organisation. E.g. having two objects that provide the same base interface should implement the same interface so that I can write code for their generic behaviour which the two can share and code for their specific behaviour which the two cannot share. – Aleksandra Glesaaen Sep 11 '19 at 08:56
  • What I do sometimes is use the TypeOf Function to determine what kind of "Child" the object which implements an interface is. Then use a select case, assign declare it as the actual child object and do something with it. – L8n Sep 11 '19 at 09:01
  • But to come back to your question, case 3 is ok and works. just be aware that you are not using the interface as intended... – L8n Sep 11 '19 at 09:04
  • I often use a GenericFoo class that Implements IFoo then. Then I write classes that encapsulate GenericFoo but themselves also implement IFoo, which can then be "forwarded" to the GenericFoo or be implemented in a different way. To use the child-class functions I then use a select Case with TypeOf (https://stackoverflow.com/a/1301977/10223558) to determine what to do with the object... – L8n Sep 11 '19 at 09:09
  • @L8n Thanks a lot for your insight. I agree that I am trying to get inheritance in a language where there is no inheritance by using interfaces in unintended ways. I will try to keep that in mind when I develop further and see if I can use composition more often and leave the interfaces to their intended use. – Aleksandra Glesaaen Sep 11 '19 at 09:14
  • First declare `Dim MyGreeter As IGreeter`, and then `Set MyGreeter = New PoliteGreeter`. Then you can use `MyGreeter.Greet`. – Domenic Sep 11 '19 at 13:22

0 Answers0