我实际上是在开发我的第一个VBA项目。 (来自C ++)
我想通过实现类和多态来改进Microsoft Excel工作簿使用的现有VBA项目。
我的问题是:
1 - 我阅读了很多文章/论坛,解释说VBA不是面向对象编程(OOP)语言,不支持多态性。
其中一些人使用关键字Implements提出了一种解决方法。
2 - 我还发现了一些像this one这样的网页,它们解释了如何使用Inherits,Overrides,Overridable,MustOverrides等关键字在VBA中执行OOP和多态。
所以我的问题是:
VBA是OOP语言,它是否支持多态?
OOP坐在4个“支柱”上:
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
很容易分辨出这个Test
程序一目了然,因为抽象级别非常高:实现细节被抽象成更专业的对象和方法。PublicNotCreatable
,有效地将类型暴露给其他VBA项目 - 并且通过一些努力(通过导出类模块,在您喜欢的文本编辑器中打开它,手动编辑类属性,并重新导入模块),可以实现实际的只读类型。没有参数化构造函数的事实是无关紧要的 - 只需编写一个工厂方法,它接受您喜欢的所有参数并返回一个实例。这是COM,COM无论如何都喜欢工厂。
下面是一个例子,说明上面代码片段中的HotelFinder
类如何封装一个Collection
对象并且只通过Property Get
访问器公开它 - 这个类之外的代码根本不能Set
这个引用,它是封装的:
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
Implements
允许你实现抽象接口(以及具体类),然后你可以编写针对ISomething
抽象的代码,它也可以是Foo
或Bar
(给定Foo
和Bar
都实现ISomething
) - 以及所有代码需要看到的是ISomething
。方法重载是VBA缺乏的语言特性,但重载与多态无关,即the ability to present the same interface for differing underlying forms (data types)。
这是应用多态的一个例子 - LogManager.Register
方法很乐意使用任何实现ILogger
接口的对象;这里有一个DebugLogger
和一个FileLogger
- 两个截然不同的接口实现,正在注册;当稍后调用LogManager.Log(ErrorLevel, Err.Description)
时,这两个实现将各自执行自己的操作; DebugLogger
将输出到即时工具窗口,FileLogger
将在指定的日志文件中写入一个条目:
LogManager.Register DebugLogger.Create("MyLogger", DebugLevel)
LogManager.Register Filelogger.Create("TestLogger", ErrorLevel, "C:\Dev\VBA\log.txt")
现在的问题是,一种不支持继承的语言是否可以被称为“面向对象”?事实证明,组合通常比继承更受欢迎,这有一些警告。 VBA会让你根据自己的内心构建对象。
VBA是OOP语言吗?
鉴于所有缺少的是继承,并且该组合比继承更可取,我很想回答“是”。我之前编写过完整的OOP VBA代码(模型 - 视图 - 演示者,工作单元和存储库,任何人?),我不会用支持继承的“真正的OOP”语言编写任何不同的代码。
以下是几个例子,全部是100%VBA:
最后一个链接中的代码最终被移植到C#,并迅速演变为a COM add-in for the VBA IDE,为您提供重构,更好的导航,代码检查和其他工具。
VBA只是限制你做它。
简短的答案是否定的。
VBA是基于对象的,允许您定义类并创建对象的实例,但它缺少通常与完全成熟的OOP语言相关联的功能,例如:
Class_Inititalize
事件,它可以做一些构造但不能参数。传递参数需要公共factory function解决方法仍然需要创建构造函数样式的设计模式。Implements
)在一定程度上实现,尽管不存在重载函数(例如)的能力,并且每个“重载”在技术上都需要唯一的函数名称。您可以通过将对象作为函数或子的唯一参数传入并根据属性的值更改过程来解决此问题。因此,虽然您可以在一定程度上使用对象,而MS Office应用程序基于对象模型,但VBA并不是一种面向对象的语言。多态性无法在C ++中熟悉的程度上实现。