我实际上正在处理我的第一个 VBA 项目。 (来自 C ++ )
我想通过实现类和多态来改进 Microsoft Excel 工作簿使用的现有 VBA 项目。
我的问题是:
1 - 我读了很多文章/论坛,解释 VBA 不是面向对象的编程( OOP )语言不支持多态性。
其中一些人建议使用关键字实施。
进行解决方法2 - 我还发现了一些像this one这样的网页,这些网页解释了如何使用继承,重写等关键字在VBA中执行OOP和多态性/ strong>,可覆盖, MustOverrides 。
所以我的问题是:
VBA 是 OOP 语言,是否支持多态?
答案 0 :(得分:78)
OOP坐在4“支柱”上:
抽象 - 通过在类模块中定义对象,可以轻松完成抽象逻辑和概念。严格地说,抽象也可以通过使用有意义的标识符并将过程代码提取到方法(类成员)中来实现。
以下是用VBA编写的演示抽象的过程示例:
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
访问者公开它的示例 - 此外的代码class简直不能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
允许您实现抽象接口(以及具体类),然后您可以针对{{1}编写代码抽象也可以是ISomething
或Foo
(给定Bar
和Foo
都实现Bar
) - 以及所有需要的代码见ISomething
。方法重载是VBA缺少的语言特性,但重载与多态无关,即 the ability to present the same interface for differing underlying forms (data types) 。
以下是应用多态的示例 - ISomething
方法很乐意使用任何实现LogManager.Register
接口的对象;这里有一个ILogger
和一个DebugLogger
- 两个完全不同的接口实现,正在注册;当稍后调用FileLogger
时,这两个实现将各自执行自己的操作; LogManager.Log(ErrorLevel, Err.Description)
将输出到 immediate 工具窗口,DebugLogger
会将一个条目写入指定的日志文件中:
FileLogger
继承 - VBA不允许您从另一个类型派生类型:不支持继承。
现在问题是,可以将不支持继承的语言限定为“面向对象”吗?事实证明组合通常比继承更可取,有一些警告。而且VBA会让你将对象组合成你心中的内容。
VBA是OOP语言吗?
鉴于所有缺少的是继承,并且该组合比继承更好,我很想回答“是”。我之前编写过完整的OOP VBA代码(模型 - 视图 - 演示者,工作单元和存储库,任何人?),我不会用支持继承的“真正的OOP”语言编写任何不同的代码。
以下是几个例子,全部是100%VBA:
最后一个链接中的代码最终被移植到C#,并迅速演变为a COM add-in for the VBA IDE,为您提供重构,更好的导航,代码检查和其他工具。
VBA只是你做的限制。
答案 1 :(得分:4)
简短的答案是否定的。
VBA是基于对象的,允许您定义类并创建对象的实例,但它缺少通常与完全成熟的OOP语言相关联的功能,例如:
Class_Inititalize
事件,可以执行某些构造但不能接受参数。传递参数需要公共factory function解决方法仍然需要创建构造函数样式的设计模式。Implements
)在一定程度上实现,尽管不存在重载函数(例如)的能力,并且每个“重载”在技术上都需要唯一的函数名称。您可以通过将对象作为函数或子的唯一参数传入并根据属性的值更改过程来解决此问题。因此,虽然您可以在一定程度上使用对象,而MS Office应用程序基于对象模型,但VBA并不是一种面向对象的语言。在C ++中你不熟悉多态性。