在VBA中使用预定义的类作为命名空间

5 浏览
0 Comments

在VBA中使用预定义的类作为命名空间

在使用VBA进行编码时,我最大的问题之一是完全缺乏命名空间,这使得很难确保作用域和选择正确的函数,因为相同名称的每个函数都在全局命名空间中。我知道你可以在函数调用前用模块名作为前缀,但我认为这也可以通过用预声明的类替换所有模块来实现。一个命名空间看起来可能是这样的:

VERSION 1.0 CLASS
BEGIN
  MultiUse = -1  'True
END
Attribute VB_Name = "MyNamespace"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = False
'@Folder("Project.Namespace")
Option Explicit
Public Function Foo() As String
    Foo = "bar"
End Function
' Opionally make sure users do not use this as a class
Private Sub Class_Initialize()
    If Not Me Is MyNamespace Then
        Err.Raise 512, _
            Source:="MyNamespace.Initialize", _
            Description:="Cannot create an instance of a namespace."
    End If
End Sub

因此,如果你想在这个命名空间中调用Foo,你必须写成MyNamespace.Foo(),而直接调用Foo()将不起作用。

我的问题是:

有没有任何理由不这样做?据我所知,类的构造函数只在你打开项目后第一次调用其任何函数时被调用,所以我看不到任何开销,但可能有一些我不知道的诡计。当然,这绝不是解决这个功能缺失的理想方式,但这并不意味着VBA程序员不会已经以迂回的方式使用语言来提供缺失的功能。

另外,我注意到这基本上与这个问题是一样的,然而我还想知道在代码中有大量预声明的“空”类是否会有任何特定问题。比如,用100个预声明的类替换100个模块,是否会对性能/稳定性等产生重大影响?

0
0 Comments

问题的出现的原因是,VBA中没有命名空间的概念,而且每个UserForm模块都会自动创建一个实例。这导致在代码中使用预声明的类作为命名空间时,可能会出现命名冲突的问题。

解决方法是重新考虑设计,避免创建空的类。如果一个类只是为了将其成员函数隔离在一个作用域内而存在,可以将其替换为一个模块。另外,应该尽量将代码结构化,使其看起来和感觉像是一个对象层次结构/模型。

通过将模块中的实用函数转换为空的类,可以清理全局命名空间并且更容易使用较短且具有描述性的函数名(通过类限定符)。这类似于其他支持命名空间的语言中的命名空间的工作方式。

但是需要注意的是,一个空类是指仅存在于范围内的类,而不是没有任何属性或方法的类。在设计时应该避免创建具有全局状态的预声明对象,因为这会导致对状态的不可控变更。

总结起来,VBA中没有命名空间的概念,但可以通过重新设计和使用空类来模拟命名空间的功能。通过结构化代码,并避免在全局命名空间中引入状态,可以提高代码的可读性和维护性。

0
0 Comments

在VBA中,我们可以使用预定义的类作为命名空间来组织和访问方法和属性。然而,有时候我们仍然需要通过引用类名来调用封装的方法。那么,相比于引用适当的模块名来调用正确模块中的方法,这样做有什么区别呢?

假设我们有一个名为MyNamespace的类,其中包含一个名为Foo的方法。我们可以通过以下方式调用这个方法:MyNamespace.Foo()。这样无论MyNamespace是一个具有预定义id的类名,还是一个模块名,此行代码似乎都能实现相同的结果。

那么,为什么我们需要引用类名来调用封装的方法呢?这是因为在VBA中,类和模块有不同的作用和特性。类是一种自定义的数据类型,可以包含属性和方法,并且可以实例化为对象。而模块是一种容器,用于组织和封装代码,可以包含过程、函数和变量。

使用类名来调用封装的方法的原因可能是我们希望在不实例化类对象的情况下直接调用这些方法。这样做可以避免创建不必要的对象实例,从而提高性能和内存管理。另外,有时候我们可能需要在类方法之间共享数据,或者在类方法中使用类级别的变量,这时候引用类名就变得必要了。

那么,有没有什么解决方法可以避免直接引用类名呢?一个解决方法是将方法定义在模块中,而不是类中。这样我们就可以直接引用模块名来调用方法,而不需要引用类名。另外,我们还可以使用静态类成员来实现类级别的方法和属性,并通过引用类名来访问它们。

使用预定义的类作为命名空间来组织和访问方法和属性是VBA中的一种常见做法。尽管有时候我们仍然需要引用类名来调用封装的方法,但我们也可以通过将方法定义在模块中或使用静态类成员来实现类级别的功能,从而避免直接引用类名。这样可以更方便地组织和管理代码,提高性能和内存管理。

0