如何限制标准模块中的功能范围
How to limit scope of functions in a standard module
我准备了一个标准模块,MyPath
,其中包含一些有用的功能。在这种情况下,标准模块对我来说比 class 模块更好。
写起来舒服多了:
Dim ext As String
ext = MyPath.getFileExtension("test.docx") ' returns "docx"
而不是:
Dim Pth As MyPath
Set Pth = New MyPath
Dim ext As String
ext = Pth.getFileExtension("test.docx")
或类似
Dim ext As String
With New MyPath
ext = .getFileExtension("test.docx")
End With
我的“伪静态-class”模块的唯一问题是它的范围(和 IntelliSense 使用)。
Dim ext As String
ext = getFileExtension("test.docx") ' This works, but I don't want it to
我想实现的是:
- 如果在调用函数时没有指定
MyPath
,智能感知不会提示模块中的方法,也无法使用它们。
- 为了使用来自
MyPath
模块的任何方法,需要输入 MyPath.
,在点之后 IntelliSense 应该建议来自模块的方法。
我尝试了一些与 Option Private Module
、Private
函数的组合,但没有人按照我描述的方式工作。
我正在准备很多 classes 和类似的模块,我会保持一切井井有条。
编辑
简而言之,如果我没有为函数或子函数指定“父”模块,我想强制编译器抛出错误。同时,如果我键入我的模块的名称,我将能够使用 IntelliSense(没有 run/call 的解决方案,只需键入模块名称、点和 select 成员)。
您描述的行为实际上可以通过预先声明的 Class 实现,但需要一些准备工作。
要预先声明 class,您可以编写一个 class,其中包含您想要的任何函数。然后将其导出为文本 (.cls) 并进行编辑,将 Attribute VB_PredeclaredId
设置为 True。那就re-import吧。我的 Class 名为 PredeclaredClass
,在 .cls 文件中看起来像这样:
VERSION 1.0 CLASS
BEGIN
MultiUse = -1 'True
END
Attribute VB_Name = "PredeclaredClass"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = False
Attribute VB_Ext_KEY = "Rubberduck" ,"Predeclared Class Module"
Option Explicit
Public Sub ThisIsVisible()
End Sub
导入此 class 后,您现在可以仅通过引用 class 模块(无需新实例)来使用其方法。
如果没有模块引用,您将无法在智能感知中看到它,也无法使用它的功能。如果您使用 Option Explicit
,编译器会报错
顺便说一下,Rubberduck 使这很容易做到,而不需要 export/import 模块。
受 VBA 的 Err 对象启发的另一个解决方案是实现一个函数,该函数 returns 引用您的“静态对象”
Public Static Function MyPath() As PathObject
Dim result As PathObject
If result Is Nothing Then Set result = New PathObject
Set MyPath = result
End Function
其中 PathObject
是包含所有伪静态方法的 class。
这种方法有一个额外的好处,即调用者不能将他们的 MyPath 引用设置为 Nothing - 以防你决定你的静态模块应该是有状态的(可能是为了一些昂贵的初始化例程)
PS 我认为 Static Function
语法很可爱,但你同样可以只用静态关键字声明结果
事实上,您可以使用
使其更加简洁
Public Static Function MyPath() As PathObject
Dim result As New PathObject
Set MyPath = result
End Function
未测试,但应该具有 MyPath
仅在第一次使用时实例化,但此后无限期挂起的行为
我准备了一个标准模块,MyPath
,其中包含一些有用的功能。在这种情况下,标准模块对我来说比 class 模块更好。
写起来舒服多了:
Dim ext As String
ext = MyPath.getFileExtension("test.docx") ' returns "docx"
而不是:
Dim Pth As MyPath
Set Pth = New MyPath
Dim ext As String
ext = Pth.getFileExtension("test.docx")
或类似
Dim ext As String
With New MyPath
ext = .getFileExtension("test.docx")
End With
我的“伪静态-class”模块的唯一问题是它的范围(和 IntelliSense 使用)。
Dim ext As String
ext = getFileExtension("test.docx") ' This works, but I don't want it to
我想实现的是:
- 如果在调用函数时没有指定
MyPath
,智能感知不会提示模块中的方法,也无法使用它们。 - 为了使用来自
MyPath
模块的任何方法,需要输入MyPath.
,在点之后 IntelliSense 应该建议来自模块的方法。
我尝试了一些与 Option Private Module
、Private
函数的组合,但没有人按照我描述的方式工作。
我正在准备很多 classes 和类似的模块,我会保持一切井井有条。
编辑
简而言之,如果我没有为函数或子函数指定“父”模块,我想强制编译器抛出错误。同时,如果我键入我的模块的名称,我将能够使用 IntelliSense(没有 run/call 的解决方案,只需键入模块名称、点和 select 成员)。
您描述的行为实际上可以通过预先声明的 Class 实现,但需要一些准备工作。
要预先声明 class,您可以编写一个 class,其中包含您想要的任何函数。然后将其导出为文本 (.cls) 并进行编辑,将 Attribute VB_PredeclaredId
设置为 True。那就re-import吧。我的 Class 名为 PredeclaredClass
,在 .cls 文件中看起来像这样:
VERSION 1.0 CLASS
BEGIN
MultiUse = -1 'True
END
Attribute VB_Name = "PredeclaredClass"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = False
Attribute VB_Ext_KEY = "Rubberduck" ,"Predeclared Class Module"
Option Explicit
Public Sub ThisIsVisible()
End Sub
导入此 class 后,您现在可以仅通过引用 class 模块(无需新实例)来使用其方法。
如果没有模块引用,您将无法在智能感知中看到它,也无法使用它的功能。如果您使用 Option Explicit
顺便说一下,Rubberduck 使这很容易做到,而不需要 export/import 模块。
受 VBA 的 Err 对象启发的另一个解决方案是实现一个函数,该函数 returns 引用您的“静态对象”
Public Static Function MyPath() As PathObject
Dim result As PathObject
If result Is Nothing Then Set result = New PathObject
Set MyPath = result
End Function
其中 PathObject
是包含所有伪静态方法的 class。
这种方法有一个额外的好处,即调用者不能将他们的 MyPath 引用设置为 Nothing - 以防你决定你的静态模块应该是有状态的(可能是为了一些昂贵的初始化例程)
PS 我认为 Static Function
语法很可爱,但你同样可以只用静态关键字声明结果
事实上,您可以使用
使其更加简洁Public Static Function MyPath() As PathObject
Dim result As New PathObject
Set MyPath = result
End Function
未测试,但应该具有 MyPath
仅在第一次使用时实例化,但此后无限期挂起的行为