【问题标题】:Is VBA an OOP language, and does it support polymorphism?VBA 是 OOP 语言吗?它是否支持多态性?
【发布时间】:2015-10-29 17:44:47
【问题描述】:

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

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

我的问题是:

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

他们中的一些人提出了一种使用关键字Implements的解决方法。

2 - 我还发现了一些网页,例如 this one,它们解释了如何在 VBA 中使用 InheritsOverrides 等关键字执行 OOP 和多态性>、可覆盖MustOverrides

所以我的问题是:

VBA是一种OOP语言吗,是否支持多态性?

【问题讨论】:

  • 第 2 点是关于 VB,而不是 VBA。 VBA中没有InheritsOverridesOverridableMustOverrides这样的关键字。
  • 好的,但我认为 VBA 是用于应用程序的 VB。是不是同一种基础语言?
  • Visual Basic for Applications (VBA) 是一种用于编写宏的事件驱动、面向对象的编程语言,用于整个 Office 套件以及其他应用程序......这是由stackoverflow :)。 Here 一些关于 VBA 中 Implements 的帖子。
  • VBA 很像 Visual Studio 版本 6 和更早版本中的 VB。 VB 现在是 VB.NET。 VB.NET 的大部分内容不在 VBA 中。
  • Here Implments 的好例子。

标签: excel vba oop polymorphism


【解决方案1】:

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 过程的作用一目了然很容易,因为抽象级别非常高:实现细节抽象的 em> 转向更专业的对象和方法。

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

    这是一个示例,说明上述 sn-p 中的 HotelFinder 类如何封装 Collection 对象并仅通过 Property Get 访问器公开它 - 此类之外的代码根本无法 @ 987654340@ 这个引用,它是封装的

     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 抽象编写代码,它也可以是FooBar(假设 FooBar 都实现了 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 将输出到 immediate 工具窗口,FileLogger 将在指定的日志文件中写入一个条目:

     LogManager.Register DebugLogger.Create("MyLogger", DebugLevel)
     LogManager.Register Filelogger.Create("TestLogger", ErrorLevel, "C:\Dev\VBA\log.txt")
    
  • 继承 - VBA 不允许您从另一个类型派生:不支持继承。


现在的问题是,不支持继承的语言是否可以称为“面向对象”?事实证明,组合通常比继承更可取,其中有许多警告。 VBA 将让您组合对象随心所欲。

VBA 是 OOP 语言吗?

鉴于缺少的只是继承,而组合比继承更可取,我很想回答“是”。我之前已经编写过成熟的 OOP VBA 代码(模型-视图-演示器与工作单元和存储库,有人吗?),我不会用支持继承的“真正的 OOP”语言编写任何不同的代码。

这里有几个例子,都是 100% VBA:

最后一个链接中的代码最终移植到 C#,并迅速演变为 a COM add-in for the VBA IDE,它为您提供重构、更好的导航、代码检查和其他工具。

VBA 的限制与您所做的一样。

【讨论】:

  • 通过以与定义相矛盾的方式工作来实现相同的目标并不意味着您的方法与定义的方法相同。如果 OOP 需要四个方面,而您拥有其中三个方面,再加上另一种方式来实现类似于第四方面的目标,但从长远来看,这是一种非常不同且更复杂的方式,但这并不意味着您拥有所有四个方面.夸大其词:我有一辆汽油车,如果我把柴油放在里面然后把它推到某个地方,并不意味着我有一辆柴油车。
  • 顺便说一下,我是您的 Rubberduck 插件的忠实粉丝。一个简单的 VBA 单元测试框架是天赐之物,加上一个真正有用的项目浏览器!我假设您希望它是 OOP 时切换到 C# :P
  • OOP 不需要继承,它只需要多态。感谢您对项目的补充。我们切换到 C# 不是因为我们希望它是 OOP,我们切换到 C# 是因为它更易于管理并且 它是 OOP 的风格 没有相同的限制。
  • 我为我提出的每一点添加了一些全 VBA 示例。没有比这更面向对象的代码了。
【解决方案2】:

简短的回答是不和不。

VBA 是基于对象的,允许您定义类和创建对象实例,但它缺少通常与成熟的 OOP 语言相关联的功能,例如:

  • 封装和抽象:VBA 在一定程度上提供了这一点。类可以通过定义的公共接口保持私有,但是类中没有构造函数的规定。类有一个Class_Inititalize 事件,它可以做一些构造但不能接受参数。传递参数需要公共 factory function 变通方法才能创建构造函数风格的设计模式。
  • 继承:在 VBA 中并不真正存在,但可以是 almost replicated
  • 多态性:可以通过接口(使用Implements)在一定程度上实现,尽管不存在重载函数的能力(例如)并且每个“重载”在技术上都需要一个唯一的函数名。您可以通过将对象作为唯一参数传递给函数或子函数来解决此问题,并根据属性的值改变过程。

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

【讨论】:

  • VBA 可能不支持继承,但它确实支持composition,这在很多方面都是实现同一目的的不同方式。
  • 我很想争辩说,事实上,从大多数定义来看,VBA 是一种面向对象的语言,但它忽略了人们在 Java 或 C# 等健壮的 OO 语言中所使用的许多常见特性.
  • @Blackhawk 我不知道,它甚至不提供继承,我认为这是面向对象的基本要求。我可能会坚持使用支持一些面向对象特性的基于对象的语言。
  • 在我看来,OOP 中继承的目的是起到重用和多态的作用。组合和接口是实现相同目标的另一种方式,实际上有时是更好的选择(参见diamond problem)。我同意重用和多态对于 OOP 是必要的,而 VBA 拥有它们。请参阅 OOP 的 SOLID 原则并将它们与 VBA 功能进行比较。
  • 话虽如此,如果 VBA 是 OOP,那它绝对是 OO 语言的混蛋。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-10-26
  • 2011-01-05
  • 2017-08-03
  • 1970-01-01
  • 2016-10-22
  • 2023-04-10
  • 1970-01-01
相关资源
最近更新 更多