Here are a few theoretical and practical contributions to the answers to them, if people come here who are wondering what tools / interfaces are.
As you know, VBA does not support inheritance, so we can almost blindly use interfaces to implement common properties / behavior in different classes. However, I find it helpful to describe what the conceptual difference between the two is in order to understand why this matters later.
- Inheritance: defines the is-a relationship (a square is a shape);
- Interfaces: Define a required relationship (a typical example is the
drawable interface, which requires the receiver to implement the draw method). This means that classes originating from different root classes can implement normal behavior.
Inheritance means that the base class (some physical or conceptual archetype) is extended, while interfaces implement a set of properties / methods that define a specific behavior.
Thus, we can say that Shape is a base class from which all other forms are inherited, which can implement the drawable interface to make all forms accessible. This interface will be a contract that ensures that each Shape has a draw method that determines how / where the figure should be drawn: a circle may or may not be made other than a square.
IDrawable class:
'IDrawable interface, defining what methods drawable objects have access to Public Function draw() End Function
Since VBA does not support inheritance, we are automatically forced to choose the IShape interface for creating the interface, which ensures that certain properties / behavior will be implemented using common shapes (square, circle, etc.), instead of creating an abstract base layer of the form from which we can spread.
IShape class:
'Get the area of a shape Public Function getArea() As Double End Function
The part in which we get into trouble is when we want to make each shape fit.
Unfortunately, since IShape is an interface, not a base class in VBA, we cannot implement the drawable interface in a base class. It seems that VBA does not allow us to use one interface for another; after checking this, the compiler does not seem to provide the desired behavior. In other words, we cannot implement IDrawable inside IShape and expect IShape instances to be forced to implement IDrawable methods because of this.
We are forced to implement this interface for every generic form class that implements the IShape interface, and, fortunately, VBA allows you to implement several interfaces.
cSquare class:
Option Explicit Implements iShape Implements IDrawable Private pWidth As Double Private pHeight As Double Private pPositionX As Double Private pPositionY As Double Public Function iShape_getArea() As Double getArea = pWidth * pHeight End Function Public Function IDrawable_draw() debug.print "Draw square method" End Function 'Getters and setters
The next part that follows now is where the typical use / benefits of an interface come into play.
Let our code begin by writing a factory that returns a new square. (This is just a workaround for our inability to send arguments directly to the constructor):
mFactory module:
Public Function createSquare(width, height, x, y) As cSquare Dim square As New cSquare square.width = width square.height = height square.positionX = x square.positionY = y Set createSquare = square End Function
Our main code will use factory to create a new square:
Dim square As cSquare Set square = mFactory.createSquare(5, 5, 0, 0)
When you look at the methods that you have at your disposal, you will notice that logically you get access to all the methods defined in the cSquare class:

We will see later why this is relevant.
Now you should be wondering what happens if you really want to create a collection of available objects. Your application may contain objects that are not shapes, but which are still available. Theoretically, nothing prevents you from having an IComputer interface that you can draw (maybe some kind of clipart or something else).
The reason you might need a collection of available objects is because you can display them in a loop at a certain point in the application's life cycle.
In this case, I will write a decorator class that wraps the collection (we will see why). class collDrawables:
Option Explicit Private pSize As Integer Private pDrawables As Collection 'constructor Public Sub class_initialize() Set pDrawables = New Collection End Sub 'Adds a drawable to the collection Public Sub add(cDrawable As IDrawable) pDrawables.add cDrawable 'Increase collection size pSize = pSize + 1 End Sub
The decorator allows you to add some convenient methods that cannot be provided in vba collections, but the actual point here is that the collection will only accept objects that can be rendered (implement the IDrawable interface). If we try to add an object that is not valid, a type mismatch will be selected (only valid objects are allowed!).
Thus, we could program the cycle of creating objects with the ability to draw. Allow an unattractive object in the collection will result in an error. The rendering outline might look like this:
Explicit option
Public Sub app() Dim obj As IDrawable Dim square_1 As IDrawable Dim square_2 As IDrawable Dim computer As IDrawable Dim person as cPerson 'Not drawable(!) Dim collRender As New collDrawables Set square_1 = mFactory.createSquare(5, 5, 0, 0) Set square_2 = mFactory.createSquare(10, 5, 0, 0) Set computer = mFactory.createComputer(20, 20) collRender.add square_1 collRender.add square_2 collRender.add computer 'This is the loop, we are sure that all objects are drawable! For Each obj In collRender.getDrawables obj.draw Next obj End Sub
Note that the above code adds a lot of transparency: we declared the objects as IDrawable, which makes it transparent, that the loop will never fail, since the draw method is available for all objects in the collection.
If we try to add Person to the collection, this will cause a type mismatch if this Person class does not implement a paintable interface.
But perhaps the most important reason that declaring an object as an interface is important is that we want to expose the methods that were defined in the interface , and not the public methods that were defined on separate classes, as we saw before.
Dim square_1 As IDrawable

We are not only sure that square_1 has a draw method, but also ensures that only methods defined by IDrawable are detected.
For a square, the advantage of this may not be immediately clear, but let's take a look at the analogy from the Java collection framework, which is much clearer.
Imagine that you have a common interface called IList , which defines the set of methods used for different types of lists. Each type of list is a specific class that implements the IList interface, defines their own behavior, and possibly adds more native methods from above.
We declare the list as follows:
dim myList as IList 'Declare as the interface! set myList = new ArrayList 'Implements the interface of IList only, ArrayList allows random (index-based) access
In the above code, declaring the list as IList ensures that you will not use methods specific to ArrayList, but only those methods that are specified by the interface. Imagine you declared a list as follows:
dim myList as ArrayList 'We don't want this
You will have access to the public methods defined in the ArrayList class. Sometimes this may be desirable, but often we just want to use the internal behavior of the class and not be defined by the public methods of the class.
The advantage becomes clear if we use this ArrayList 50 more times in our code, and suddenly we find that we are better off using a LinkedList (which allows for specific internal behavior associated with this type of list).
If we run the interface, we can change the line:
set myList = new ArrayList
to:
set myList = new LinkedList
and none of the other codes will break, as the interface ensures that the contract is completed, i.e. only the public methods defined in IList are used, therefore various types of lists are replaceable over time.
The last thing (perhaps a lesser known behavior in VBA) is that you can provide a default interface
We can define an interface as follows:
IDrawable:
Public Function draw() Debug.Print "Draw interface method" End Function
and a class that also implements the draw method:
cSquare:
implements IDrawable Public Function draw() Debug.Print "Draw square method" End Function
We can switch between implementations as follows:
Dim square_1 As IDrawable Set square_1 = New IDrawable square_1.draw 'Draw interface method Set square_1 = New cSquare square_1.draw 'Draw square method
This is not possible if you declare the variable as cSquare.
I cannot immediately come up with a good example when this can be useful, but technically it is possible if you test it.