VBA inheritance scheme

VBA is COM-based, and COM does not perform inheritance. But I think that I can have a sample that approximates some of its aspects:

Animal.cls

Public Sub Speak() Err.Raise 418, , "Not supported" End Sub 

Dog.cls

 Implements Animal Private mBase As Animal Private Sub Class_Initialize() Set mBase = New Animal End Sub Private Sub Animal_Speak() Me.Speak End Sub Public Sub Speak() MsgBox "Woof!" End Sub Public Property Get Base() As Animal Set Base = mBase End Property 

Test.bas

 Sub Test() Dim animal As animal: Set animal = New dog Dim dog As dog: Set dog = New dog Dim object As Object: Set object = New dog dog.Speak ' direct : Woof! animal.Speak ' polymorphic : Woof! object.Speak ' late-bound : Woof! dog.Base.Speak ' fake upcast : Err 418 End Sub 

Thus, a member of the Animal_Speak interface implemented in Dog.cls (which is private so that it is not called directly) redirected the call to the public Speak method, which can either delegate it to the equivalent element in Animal.cls (to 'inherit') or replace it with something else (to "override").

In addition, the Base property in Dog.cls is displayed if the caller really wants the base behavior (for "upcast").

(terms are in quotation marks because they are only approximations).

So my questions are:

  • Is this a well-known pattern, and if so, is it common?
  • Are there any disadvantages?
+5
source share
1 answer

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 .

+6
source

Source: https://habr.com/ru/post/1272056/


All Articles