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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/31858094/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 09:52:14  来源:igfitidea点击:

Is VBA an OOP language, and does it support polymorphism?

excelvbaooppolymorphism

提问by Axel Borja

I am actually working on my first VBAproject. (come from C++)

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

I would like to improve an existing VBAproject used by a Microsoft Excelworkbook by implementing classes and polymorphism.

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

My problem is:

我的问题是:

1 -I read a lot of articles/forums which explain that VBAis not an Object Oriented Programming (OOP) language and do not support Polymorphism.

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

Some of them propose a workaround using the keyword Implements.

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

2 -I also found some webpages like this onewhich explain how to perform OOP and polymorphism in VBA using keywords like Inherits, Overrides, Overridable, MustOverrides.

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

So my question is :

所以我的问题是:

Is VBAan OOPlanguage, and does it support polymorphism ?

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

回答by Mathieu Guindon

OOP is sitting on 4 "pillars":

OOP 坐拥 4 个“支柱”:

  • checkAbstraction- Abstracting logic and concepts can easily be done by defining objects in class modules. Strictly speaking, abstractionis also achieved by using meaningful identifiers and extracting procedural code into methods (class members).

    Here's an example of a procedure written in VBA that demonstrates abstraction:

    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
    

    It's easy to tell what this Testprocedure does at a glance, because the abstraction levelis very high: the implementation detailsare abstractedaway into more specialized objects and methods.

  • checkEncapsulation- Classes can have private fields exposed by properties; classes can be made PublicNotCreatable, effectively exposing types to other VBA projects - and with a little bit of effort (by exporting the class module, opening it in your favorite text editor, manually editing class attributes, and re-importing the module), you can achieve actual read-only types. The fact that there are no parameterized constructors is irrelevant - just write a factory method that takes all the parameters you like and return an instance. This is COM, and COM likes factories anyway.

    Here's an example of how the HotelFinderclass from the above snippet encapsulatesa Collectionobject and only exposes it through a Property Getaccessor - code outside this class simply cannot Setthis reference, it's encapsulated:

    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
    
  • checkPolymorphism- Implementslets you implement abstract interfaces (and concrete classes, too), and then you can write code against an ISomethingabstraction that can just as well be a Fooor a Bar(given Fooand Barboth implement ISomething) - and all the code ever needs to see is ISomething. Method overloading is a language feature that VBA lacks, but overloading has nothing to do with polymorphism, which is the ability to present the same interface for differing underlying forms (data types).

    Here's an example of applied polymorphism - the LogManager.Registermethod is happy to work with any object that implements the ILoggerinterface; here a DebugLoggerand a FileLogger- two wildly different implementations of that interface, are being registered; when LogManager.Log(ErrorLevel, Err.Description)is invoked later, the two implementations will each do their own thing; DebugLoggerwill output to the immediatetoolwindow, and FileLoggerwill write an entry into a specified log file:

    LogManager.Register DebugLogger.Create("MyLogger", DebugLevel)
    LogManager.Register Filelogger.Create("TestLogger", ErrorLevel, "C:\Dev\VBA\log.txt")
    
  • nopeInheritance- VBA does not let you derive a type from another: inheritance is not supported.

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

    这是一个用 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访问器-代码这个类根本无法外面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抽象编写代码,该抽象也可以是 aFoo或 a Bar(给定Foo并且Bar都实现ISomething)-并且所有代码需要看到的是ISomething. 方法重载是VBA所缺乏的语言特性,但重载与多态无关,多态是为不同的底层形式(数据类型)呈现相同接口的能力

    下面是一个应用多态的例子——该LogManager.Register方法很乐意与任何实现该ILogger接口的对象一起工作;这里 aDebugLogger和 a 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 不允许您从另一个类型派生类型:不支持继承。



Now the question is, can a language that doesn't support inheritance be qualified as "object-oriented"?It turns out compositionis very often preferable to inheritance, which has a number of caveats. And VBA will let you composeobjects to your heart's content.

现在的问题是,不支持继承的语言是否可以称为“面向对象”?事实证明,组合通常比继承更可取,继承有很多注意事项。VBA 可以让您根据自己的喜好组合对象。

Is VBA an OOP language?

VBA 是 OOP 语言吗?

Given all that's missing is inheritance, and that composition is preferable to inheritance, I'm tempted to answer "Yes". I've written full-blown OOP VBA code before (Model-View-Presenter with Unit-of-Work and Repository, anyone?), that I wouldn't have written any differently in a "real OOP" language that supports inheritance.

鉴于缺少的只是继承,而且这种组合比继承更可取,我很想回答“是”。我以前写过完整的 OOP VBA 代码(Model-View-Presenter with Unit-of-Work 和 Repository,有人吗?),我不会用支持继承的“真正的 OOP”语言编写任何不同的代码。

Here are a few examples, all 100% VBA:

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

The code in this last link was eventually ported to C#, and quickly evolved into a COM add-in for the VBA IDEthat gives you refactorings, better navigation, code inspections, and other tools.

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

VBA is only as limiting as you make it.

VBA 的限制取决于您所做的。

回答by stucharo

The short answers are no and no.

简短的回答是否定的。

VBA is object based, allowing you to define classes and create instances of objects but it lacks the features that would normally be associated with a fully fledged OOP language, for example:

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

  • Encapsulation and abstraction: VBA provides this to an extent. Classes can be kept private with public interfaces defined, however there is no provision for constructors within classes. Classes have a Class_Inititalizeevent which can do some construction but cannot take arguments. Passing arguments would require a public factory functionworkarounds are still required to create a constructor-style design pattern.
  • Inheritance: Doesn't really exist in VBA but can be almost replicated
  • Polymorphism: Can be achieved to an extent through interfaces (using Implements) although the ability to overload functions (for example) doesn't exist and each "overload" would technically require a unique function name. You can work around this by passing in an object as the only parameter to a function or sub and vary the procedure depending on the values of the properties.
  • 封装和抽象:VBA 在一定程度上提供了这一点。类可以通过定义的公共接口保持私有,但是类中没有提供构造函数。类有一个Class_Inititalize可以做一些构造但不能带参数的事件。传递参数将需要公共工厂函数解决方法仍然需要创建构造函数样式的设计模式。
  • 继承:在 VBA 中并不真正存在,但几乎可以 复制
  • 多态:可以通过接口(使用Implements)在一定程度上实现,尽管重载函数的能力(例如)不存在,并且每个“重载”在技术上都需要一个唯一的函数名称。您可以通过将对象作为唯一参数传递给函数或子来解决此问题,并根据属性值改变过程。

So while you can work with objects to an extent and MS Office applications are based around an object model, VBA is not truely an Object Oriented language. Polymorphism cannot be achieved to the extent that you would be familiar with in C++.

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