VBA是一种面向对象的语言吗?它支持多态性吗?

9 浏览
0 Comments

VBA是一种面向对象的语言吗?它支持多态性吗?

我实际上正在开展我的第一个VBA项目。 (来自C ++)

我想通过实现类和多态性来改进一个用于Microsoft Excel工作簿的现有VBA项目。

我的问题是:

1 - 我阅读了很多解释VBA不是面向对象编程(OOP)语言且不支持多态性的文章/论坛。

其中一些提出了使用关键字Implements的解决方法。

2 - 我还发现了一些网页,比如这个网页,它解释了如何在VBA中使用InheritsOverridesOverridableMustOverrides等关键字进行OOP和多态性。

所以我的问题是:

VBA是一种面向对象编程语言,并且它支持多态性吗?

admin 更改状态以发布 2023年5月24日
0
0 Comments

简短的回答是不和不。

VBA是基于对象的,允许您定义类并创建对象实例,但缺乏通常与完整的OOP语言相关的功能,例如:

  • 封装和抽象:VBA在一定程度上提供了这个功能。类可以保持私有,定义公共接口,但是类中没有构造函数的提供。类有一个Class_Inititalize事件可以做一些构造,但无法传递参数。传递参数需要一个公共工厂函数,仍需要解决创建构造函数样式设计模式的问题。
  • 继承:在VBA中实际上不存在,但可以几乎复制
  • 多态性:可以通过界面(使用Implements)在一定程度上实现,尽管不存在函数重载的能力(例如),每个“重载”实际上都需要一个独特的函数名称。您可以通过将对象作为函数或子例程的唯一参数传递,并根据属性值的变化来改变过程来解决此问题。

因此,尽管您可以在一定程度上使用对象,而且MS Office应用程序是基于对象模型构建的,但VBA并不是真正的面向对象语言。无法实现您在C++中熟悉的多态性。

0
0 Comments

OOP建立在4个“支柱”上:

  • check 抽象 - 通过在类模块中定义对象,可以轻松地抽象逻辑和概念。严格来说,使用有意义的标识符并将过程代码提取到方法(类成员)中也可以实现抽象。

    这是一个使用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过程的作用,因为抽象级别很高: 实现细节被抽象成更专业的对象和方法。

  • check 封装 - 类可以通过属性公开私有字段;类可以被设置为PublicNotCreatable,有效地将类型暴露给其他VBA项目 - 并通过一点点努力 (导出类模块,用你喜欢的文本编辑器打开它,手动编辑类属性,然后重新导入模块),你可以实现实际的只读类型。没有参数化构造函数这一事实是无关紧要的 - 只需编写一个接受所有所需参数并返回实例的工厂方法即可。这是COM,而COM喜欢工厂。

    这是从以上片段中的HotelFinder类演示的,封装了一个Collection对象并仅通过一个Property Get访问器公开它 - 在这个类外部的代码根本无法设置此引用,它被封装:

     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
    

  • check 多态性 - Implements可以让你实现抽象接口(和具体类),然后你可以编写针对ISomething抽象的代码,这个抽象可以完全是FooBar(如果FooBar都实现了ISomething),而所有代码只需要查看ISomething。方法重载是VBA缺少的语言特性,但重载与多态性无关,多态性是呈现不同基础形式(数据类型)的相同接口的能力

    这是应用多态性的示例 - LogManager.Register方法可以处理实现ILogger接口的任何对象;这里的一个DebugLoggerFileLogger,是该接口的两个截然不同的实现,正在注册;当稍后调用LogManager.Log(ErrorLevel, Err.Description)时,两个实现将各自执行自己的操作;DebugLogger将输出到立即窗口,FileLogger将在指定的日志文件中写入一个条目:

     LogManager.Register DebugLogger.Create("MyLogger", DebugLevel)
     LogManager.Register Filelogger.Create("TestLogger", ErrorLevel, "C:\Dev\VBA\log.txt")
    

  • nope 继承 - VBA不允许您从另一个类型派生出一个类型:不支持继承。


现在的问题是,一个不支持继承的语言可以被称为"面向对象"吗?结果证明,组合往往比继承更可取,后者有许多注意事项。而VBA将让您尽情进行对象组合。

VBA是一种面向对象的语言吗?

考虑到所有缺少的是继承,以及组合优于继承,我很想回答"是的"。我以前写过充分的OOP VBA代码(Model-View-Presenter with Unit-of-Work and Repository,有人吗?),我不会在支持继承的"真正的OOP"语言中写任何不同的代码。

下面是一些100% VBA的示例:

最后一个链接中的代码最终被移植到C#,并迅速发展成为VBA IDE的一款COM插件,该插件为您提供了重构,更好的导航,代码检查和其他工具。

VBA仅限于您的想象力。

0