Как экземпляр объекта VBA может определить, является ли он экземпляром по умолчанию? - PullRequest
0 голосов
/ 20 октября 2018

Это не работает:


clsTestDefaultInstance

Dim HowAmIInitialised As Integer

Private Sub Class_Initialize()
HowAmIInitialised = 99
End Sub

Public Sub CallMe()
  Debug.Print "HowAmIInitialised=" & HowAmIInitialised
End Sub

т.е. clsTestDefaultInstance.CallMe() выводит HowAmIInitialised=99, потому что Class_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

Ответы [ 2 ]

0 голосов
/ 07 декабря 2018

Вы можете получить экземпляр по умолчанию, используя Class_Initialize и статическую функцию внутри класса для хранения экземпляра по умолчанию.

Использование примера выдержки из моего класса clsCustomer, который имеет VB_PredeclaredId = True

«Примечание. Class_Initialize вызывается при первом обращении к clsCustomer». Вы также можете делать такие вещи, как If Not Me Is clsCustomer.для одноэлементных классов, т.е. не может создать экземпляр, отличный от экземпляра по умолчанию

Private Sub Class_Initialize ()

If Me Is clsCustomer Then
    GetDefaultInstance
End If

End Sub

Статическая функция GetDefaultInstance () As clsCustomer

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

Функция завершения

В модуле для проверки

Sub TestDefaultInstance ()

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)

End Sub

Открытая функция IsDefaultInstance (byval defaultObject as Object, byval compareObject as Object) As Boolean

Dim isDefault as Boolean
if defaultObject is compareObject then
  isDefault = True
End if
IsDefaultInstance = isDefault 

End Function

Output

2401988144720 (экземпляр по умолчанию)

0 (Экземпляр pvtCustomer еще не установлен и равен нулю)

2401988144720 (экземпляр по умолчанию)

2401988142160 (Новый экземпляр pvtCustomer, который не являетсясовпадает с экземпляром по умолчанию)

False (False, возвращаемое как экземпляр объекта клиента по умолчанию, не совпадает с новым объектом pvtCustomer)

Примечания: Выходной ObjPtr будет меняться при каждом запуске, т.е.ссылки на память и только для примера.

0 голосов
/ 21 октября 2018

Это действительно очень просто ... просто сравните указатель объекта экземпляра с указателем объекта экземпляра по умолчанию:

'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

С учетом сказанного обратите внимание, что это сопровождается несколькими оговорками:

  • Это в значительной степени гарантирует, что экземпляр по умолчанию будет восстановлен, если вы проверите, является ли какой-либо экземпляр значением по умолчанию.экземпляр, потому что, как вы, вероятно, знаете, простая ссылка на экземпляр по умолчанию создаст его резервную копию, если он еще не создан.
  • Экземпляр по умолчанию может изменить если вы Unload это (для UserForm) или установите его на Nothing, а затем заставите его автоматически создать экземпляр.Лучше всего думать о VB_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
    
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...