问题描述
我实际上正在处理我的第一个 VBA 项目.(来自C++)
我想通过实现类和多态来改进 Microsoft Excel 工作簿使用的现有 VBA 项目.
我的问题是:
1 - 我阅读了很多文章/论坛,这些文章/论坛解释了 VBA 不是面向对象的编程 (OOP) 语言,并且不支持多态.
他们中的一些人提出了一种使用关键字Implements的解决方法.
2 - 我还发现了一些网页,例如 .
这是一个应用多态的例子 - LogManager.Register
方法很乐意与任何实现了 ILogger
接口的对象一起工作;这里正在注册一个 DebugLogger
和一个 FileLogger
- 该接口的两个完全不同的实现;当 LogManager.Log(ErrorLevel, Err.Description)
稍后被调用时,两个实现将各自做自己的事情;DebugLogger
将输出到 immediate 工具窗口,FileLogger
将一个条目写入指定的日志文件:
LogManager.Register DebugLogger.Create("MyLogger", DebugLevel)LogManager.Register Filelogger.Create("TestLogger", ErrorLevel, "C:DevVBAlog.txt")
继承 - VBA 不允许您派生来自另一个类型:不支持继承.
现在的问题是,一种不支持继承的语言是否可以称为面向对象"?事实证明,组合通常比继承,其中有许多注意事项.VBA 可以让您组合对象以满足您的需求.
VBA 是 OOP 语言吗?
鉴于缺少的只是继承,而且这种组合比继承更可取,我很想回答是".我以前写过完整的 OOP VBA 代码(有工作单元和存储库的模型-视图-展示器,有人吗?),我不会在真正的 OOP"中写任何不同的代码.支持继承的语言.
这里有几个例子,都是 100% VBA:
- Model-View-ViewModel 基础架构 &示例(概念验证)
- 具有模型-视图-控制器 (MVC) 架构的成熟 OOP 战舰游戏莉>
- 可重复使用的进度指示器
- 模型-视图-演示者模式
- UnitOfWork with Repository 模式
- 多态记录器
- 自动单元测试框架
最后一个链接中的代码最终被移植到 C#,并迅速演变成一个用于 VBA IDE 的 COM 插件 为您提供重构、更好的导航、代码检查和其他工具.
VBA 的局限性取决于您的能力.
I am actually working on my first VBA project. (come from C++)
I would like to improve an existing VBA project used by a Microsoft Excel workbook by implementing classes and polymorphism.
My problem is:
1 - I read a lot of articles/forums which explain that VBA is not an Object Oriented Programming (OOP) language and do not support Polymorphism.
Some of them propose a workaround using the keyword Implements.
2 - I also found some webpages like this one which explain how to perform OOP and polymorphism in VBA using keywords like Inherits, Overrides, Overridable, MustOverrides.
So my question is :
Is VBA an OOP language, and does it support polymorphism ?
OOP is sitting on 4 "pillars":
Abstraction - Abstracting logic and concepts can easily be done by defining objects in class modules. Strictly speaking, abstraction is also achieved by using meaningful identifiers and extracting procedural code into methods (class members).
Here's an example of a procedure written in VBA that demonstrates abstraction:
Public Sub Test(ByVal checkin As Date, ByVal checkout As Date, ByVal custType As CustomerType) Dim finder As New HotelFinder InitializeHotels finder Debug.Print finder.FindCheapestHotel(checkin, checkout, custType) End Sub
It's easy to tell what this
Test
procedure does at a glance, because the abstraction level is very high: the implementation details are abstracted away into more specialized objects and methods.Encapsulation - Classes can have private fields exposed by properties; classes can be made
PublicNotCreatable
, effectively exposing types to other VBA projects - and with a little bit of effort (by exporting the class module, opening it in your favorite text editor, manually editing class attributes, and re-importing the module), you can achieve actual read-only types. The fact that there are no parameterized constructors is irrelevant - just write a factory method that takes all the parameters you like and return an instance. This is COM, and COM likes factories anyway.Here's an example of how the
HotelFinder
class from the above snippet encapsulates aCollection
object and only exposes it through aProperty Get
accessor - code outside this class simply cannotSet
this reference, it's encapsulated:Private Type TFinder Hotels As Collection End Type Private this As TFinder Public Property Get Hotels() As Collection Set Hotels = this.Hotels End Property Private Sub Class_Initialize() Set this.Hotels = New Collection End Sub Private Sub Class_Terminate() Set this.Hotels = Nothing End Sub
Polymorphism -
Implements
lets you implement abstract interfaces (and concrete classes, too), and then you can write code against anISomething
abstraction that can just as well be aFoo
or aBar
(givenFoo
andBar
both implementISomething
) - and all the code ever needs to see isISomething
. Method overloading is a language feature that VBA lacks, but overloading has nothing to do with polymorphism, which is the ability to present the same interface for differing underlying forms (data types).Here's an example of applied polymorphism - the
LogManager.Register
method is happy to work with any object that implements theILogger
interface; here aDebugLogger
and aFileLogger
- two wildly different implementations of that interface, are being registered; whenLogManager.Log(ErrorLevel, Err.Description)
is invoked later, the two implementations will each do their own thing;DebugLogger
will output to the immediate toolwindow, andFileLogger
will write an entry into a specified log file:LogManager.Register DebugLogger.Create("MyLogger", DebugLevel) LogManager.Register Filelogger.Create("TestLogger", ErrorLevel, "C:DevVBAlog.txt")
Inheritance - VBA does not let you derive a type from another: inheritance is not supported.
Now the question is, can a language that doesn't support inheritance be qualified as "object-oriented"? It turns out composition is very often preferable to inheritance, which has a number of caveats. And VBA will let you compose objects to your heart's content.
Given all that's missing is inheritance, and that composition is preferable to inheritance, I'm tempted to answer "Yes". I've written full-blown OOP VBA code before (Model-View-Presenter with Unit-of-Work and Repository, anyone?), that I wouldn't have written any differently in a "real OOP" language that supports inheritance.
Here are a few examples, all 100% VBA:
- Model-View-ViewModel infrastructure & example (proof-of-concept)
- Full-blown OOP Battleship game with Model-View-Controller (MVC) architecture
- A reusable progress indicator
- Model-View-Presenter pattern
- UnitOfWork with Repository pattern
- Polymorphic logger
- Automagic Unit Testing framework
The code in this last link was eventually ported to C#, and quickly evolved into a COM add-in for the VBA IDE that gives you refactorings, better navigation, code inspections, and other tools.
VBA is only as limiting as you make it.
这篇关于VBA 是一种 OOP 语言,它是否支持多态?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!