You discover the possibilities of polymorphism in VBA by inheriting from an interface that is not the same as inheriting from a class.
With class inheritance, you can have virtual and even abstract methods for override in derived classes.
With the inheritance of the .NET interface with an interface, you can have an interface that extends another interface, and the type of implementation can implement this interface to satisfy the compiler - it provides members with all the interfaces that it extends.
With the inherited VBA interface interface, you get a class that can implement the interface. Or two. Or three. Or more .... how do COM types do.
And that .. is pretty amazing already.
It is called object-oriented programming - OOP sits on 4 things:
- Abstraction
- Sealing
- Inheritance (sad VBA)
- Polymorphism
This is a common paradigm in quite a few programming languages ββsuch as Java and C #. The ideal OOP code is SOLID, a loosely coupled code that can be easily tested. SOLID principles define many OOP designs:
- [S] ingle principle of responsibility
- [O] pen / closed principle
- [L] iskov replacement principle
- [I] nterface segregation principle
- [D] Inversion reversal principle
Despite the lack of inheritance capabilities, VBA can still respect these OOP principles while embracing its uncompromising nature of COM. An extensible log in code review, as well as a follow-up post that implements DatabaseLogger , give a pretty powerful demo.
But even without the use of interfaces, thinking in OOP allows you to encapsulate any functionality and write it in such a way that it is a reusable component. Like this reuse indicator , which illustrates how you move away from the user interface code (UserForm or worksheet) that triggers the display so that the user interface is nothing more than an I / O device in your application logic.
By studying OOP with VBA, you process your thought process and set off on a path from the procedural paradigm to the wonders of object-oriented code. Once you have mastered this, you will want to expand your experience to full class inheritance and open delegates and anonymous functions, and perhaps even look at the functional programming paradigm, which is another completely different way of thinking about code, such as OOP, is procedural.
The VBA IDE, the glorious VBE, unfortunately, was last updated when VB6 was furious, and does not have many features to support OOP. You could even say that VBE actively hates OOP:
- Project Explorer folders are just module types, so a project with many classes quickly becomes a navigation nightmare.
- There is no "go to implementation" option to easily find interface implementations.
- No refactoring tools.
- No unit testing.
- There is no static code analysis.
In fairness, we note that in 1999 such testing and refactoring methods were not so common (AFAIK). However, the lack of OOP in VBA is the lack of functions in the IDE itself.
Fortunately, VBIDE has an extensibility model and supports add-ons. So you can get Rubberduck and have all these features and write OOP code in VBA without constantly resisting the lack of IDE capabilities.
DISCLAIMER: I am running the Rubberduck open source project hosted on GitHub .
The pattern you implement is a form of composition that is a commonly used surrogate for inheritance, even in languages ββthat support class inheritance. You see that inheritance has its drawbacks, and composition is often preferred over it.
The composition does not require interfaces. In fact, whenever you encapsulate an instance of an object in a class and then expose some (or all) of the internal members of the object, you use composition.
In your specific example, you compose an "abstract class" ( Animal - interface), which does not make much sense, since the interface is not intended to be created directly:
Set mBase = New Animal
In real code, you can have an IRepository interface, ProductSqlRepository that implements it (then a SupplierSqlRepository , then OrderSqlRepository , etc.), and you could compile implementations with some SqlRepository , which provides the general functionality used by all implementations, each one in a special way: meanwhile, client code only ever needs to know / care about IRepository .