VBA是OOP语言,它是否支持多态?

Axe*_*rja 38 oop polymorphism excel vba

我实际上是在开发我的第一个VBA项目.(来自C++)

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

我的问题是:

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

其中一些人使用关键字Implements提出了一种解决方法.

2 -我还发现了一些像这样的网页,它解释了如何使用Inherits,Overrides,Overridable,MustOverrides等关键字在VBA中执行OOP和多态.

所以我的问题是:

VBA面向对象语言,它支持多态?

Mat*_*don 87

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
    
    Run Code Online (Sandbox Code Playgroud)

    很容易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
    
    Run Code Online (Sandbox Code Playgroud)
  • 校验 多态性 - Implements允许您实现抽象接口(以及具体类),然后您可以针对ISomething抽象编写代码,该抽象也可以是a Foo或a Bar(给定的FooBar两个实现ISomething) - 并且所有代码都需要查看ISomething.方法重载是VBA缺少的语言特性,但重载与多态无关,多态是为不同的底层形式(数据类型)呈现相同的接口的能力.

    这是应用多态的一个例子 - 该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")
    
    Run Code Online (Sandbox Code Playgroud)
  • 不 继承 - VBA不允许您从另一个派生类型:不支持继承.


现在的问题是,一种不支持继承的语言是否可以被称为"面向对象"?事实证明,组合通常比继承更受欢迎,这有一些警告.VBA会让你根据自己的内心构建对象.

VBA是OOP语言吗?

鉴于所有缺少的是继承,并且该组合比继承更可取,我很想回答"是".我之前编写过完整的OOP VBA代码(模型 - 视图 - 演示者,工作单元和存储库,任何人?),我不会用支持继承的"真正的OOP"语言编写任何不同的代码.

以下是几个例子,全部是100%VBA:

最后一个链接中的代码最终被移植到C#,并迅速演变为VBA IDE的COM加载项,为您提供重构,更好的导航,代码检查和其他工具.

VBA只是限制你做它.

  • 通过与定义相矛盾的方式实现相同的目标并不意味着您的方法与定义的方法相同.如果OOP需要四个方面,你有三个方面加上另一种方法来实现类似于第四方面的长期运行但是以非常不同且更加紊乱的方式实现它并不意味着你有所有四个方面.夸大其词:我有一辆汽油车,如果我把柴油放进去并把它推到某个地方并不意味着我有一辆柴油车. (5认同)
  • 顺便说一句,我是您的 Rubberduck 插件的忠实粉丝。一个简单的 VBA 单元测试框架是天赐之物,再加上一个真正有用的项目浏览器!我假设您在希望 OOP 时切换到 C# :P (2认同)
  • OOP不需要继承,它只需要多态性。顺便说一句,感谢您对项目的补充。我们没有切换到 C#,因为我们希望它是 OOP,我们切换到 C# 是因为它更容易管理,并且*它是 OOP 的风格*没有相同的限制。 (2认同)

stu*_*aro 5

简短的答案是“否”和“否”。

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

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

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

  • 话虽如此,如果VBA是OOP,那肯定是OO语言的混蛋继子。 (5认同)
  • 在我看来,OOP中继承的目的是充当重用和多态性。组合和接口是实现同一目标的另一种方法,实际上有时是更好的选择(请参阅[钻石问题](https://en.wikipedia.org/wiki/Multiple_inheritance#The_diamond_problem))。我同意重用和多态性对于OOP是必需的,而VBA拥有它们。请参阅OOP的[SOLID](https://zh.wikipedia.org/wiki/SOLID_(面向对象的设计))原理,并将其与VBA功能进行比较。 (4认同)
  • VBA可能不支持继承,但它确实支持[composition](https://en.wikipedia.org/wiki/Composition_over_inheritance),这在许多方面都是达到同一目的的不同方法。 (2认同)
  • 我很容易争辩说,从大多数定义来看,VBA实际上是一种面向对象的语言,但是它忽略了人们在健壮的OO语言(如Java或C#)中使用的许多常见功能。 (2认同)