VBA对象实例如何判断它是否为默认实例?
这不起作用:VBA对象实例如何判断它是否为默认实例?,vba,Vba,这不起作用: i、 eclsTestDefaultInstance.CallMe()outputshowamiInitialized=99,因为即使对于默认实例也会调用Class\u Initialize() VERSION 1.0 CLASS BEGIN MultiUse = -1 'True END Attribute VB_Name = "clsTestDefaultInstance" Attribute VB_GlobalNameSpace = False Attribute
i、 e
clsTestDefaultInstance.CallMe()
outputshowamiInitialized=99
,因为即使对于默认实例也会调用Class\u Initialize()
VERSION 1.0 CLASS
BEGIN
MultiUse = -1 'True
END
Attribute VB_Name = "clsTestDefaultInstance"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = False
Option Compare Database
Option Explicit
' test how class instance can tell if it is default
'clsTestDefaultInstance
Dim HowAmIInitialised As Integer
Private Sub Class_Initialize()
HowAmIInitialised = HowAmIInitialised + 1
End Sub
Public Sub CallMe()
Debug.Print "HowAmIInitialised=" & HowAmIInitialised
End Sub
这真的很简单。。。只需将实例的对象指针与默认实例的对象指针进行比较:
'TestClass.cls (VB_PredeclaredId = True)
Option Explicit
Public Property Get IsDefaultInstance() As Boolean
IsDefaultInstance = ObjPtr(TestClass) = ObjPtr(Me)
End Property
测试代码表明它工作正常:
Private Sub TestDefaultInstance()
Dim foo(9) As TestClass
Dim idx As Long
For idx = LBound(foo) To UBound(foo)
If idx = 5 Then
Set foo(idx) = TestClass
Else
Set foo(idx) = New TestClass
End If
Next
For idx = LBound(foo) To UBound(foo)
Debug.Print idx & foo(idx).IsDefaultInstance
Next
End Sub
话虽如此,请注意,这有几个注意事项:
- 如果您检查是否有任何实例是默认实例,它几乎可以保证默认实例将被重新实例化,因为您可能知道,只要引用默认实例,如果它还没有实例化,它就会被重新实例化
- 如果您
卸载它(对于
),或者将其设置为用户表单
,然后使其再次自动实例化,则默认实例可以更改。最好将无
想象成一种契约,如果直接使用类名,您将始终获得一个实例。该合同不能保证它总是相同的。将以下代码添加到上述VB\u PredeclaredId
过程的底部将演示:TestDefaultInstance
'This doesn't effect anything that stored a reference to it. Set TestClass = Nothing 'Make a call on the default to force it to reinstantiate. Debug.Print TestClass.IsDefaultInstance 'This will now be false. Debug.Print foo(5).IsDefaultInstance
Dim pvtDefaultInstance As clsCustomer
If pvtDefaultInstance Is Nothing Then
If Not Me Is Nothing Then
Set pvtDefaultInstance = Me
End If
End If
Set GetDefaultInstance = pvtDefaultInstance
端函数
在要测试的模块中
子TestDefaultInstance()
端接头
公共函数是布尔形式的默认值(byval defaultObject作为对象,byval compareObject作为对象)
Dim isDefault as Boolean
if defaultObject is compareObject then
isDefault = True
End if
IsDefaultInstance = isDefault
端函数
输出
2401988144720(默认实例)
0(pvtCustomer实例尚未设置且等于零)
2401988144720(默认实例)
2401988142160(与默认实例不同的新pvtCustomer实例)
False(返回False,因为客户默认对象实例与新的pvtCustomer对象不同)
注意:每次运行时,输出ObjPtr都会有所不同,即它们是内存引用,仅用于示例 @GSerg:恐怕这是不对的。设置
VB\u PredeclaredId=True
,然后可以创建用户定义类的全局默认实例。问题是:为什么OP需要找出他是否在使用自己类的默认实例。我觉得这很奇怪。要么你在写代码的时候就知道了,要么……该死的新手,难道他们不能正确地提问吗!在编辑的问题中列出了完整的类…那么,我是否正确地告诉您,您希望在类中知道它是由全局默认实例调用的,还是由您声明的变量调用的,对吗。我不知道这是否可能,对不起。但不管怎样,你为什么要知道这些?您编写代码,就知道它是否是默认实例。也许你在寻找类似于或的东西。@GSerg这个问题是有效的,即使它目前没有任何理由:我在寻找全局默认实例和显式创建实例之间的内在动态区别。我突然想到,Class\u Initialize()
可能不会为全局默认值调用,但我的测试表明它是(就像在该例程上放置断点一样)这是一个合理的动机:将全局实例用作单例。如果发现任何显式创建的实例,程序将失败。谢谢,向上投票。当然,你只需要比较“地址”。有时你看不见树木,也看不见森林:——)@Storax你只需要寻找树木@Storax和Comintern:说到抽象级别,更“高级”的代码可能是IsDefaultInstance=Me是TestClass
;当然,在类模块内部
If Me Is clsCustomer Then
GetDefaultInstance
End If
Dim pvtDefaultInstance As clsCustomer
If pvtDefaultInstance Is Nothing Then
If Not Me Is Nothing Then
Set pvtDefaultInstance = Me
End If
End If
Set GetDefaultInstance = pvtDefaultInstance
Dim pvtCustomer As clsCustomer
Debug.Print ObjPtr(clsCustomer.GetDefaultInstance)
Debug.Print ObjPtr(pvtCustomer)
Set pvtCustomer = New clsCustomer
Debug.Print ObjPtr(clsCustomer.GetDefaultInstance)
Debug.Print ObjPtr(pvtCustomer)
Debug.Print IsDefaultInstance(clsCustomer.GetDefaultInstance, pvtCustomer)
Dim isDefault as Boolean
if defaultObject is compareObject then
isDefault = True
End if
IsDefaultInstance = isDefault