Это общая проблема циклических ссылок. Там много всего об этом, и общий вывод состоит в том, что их следует избегать как можно больше.
Поэтому вы правы, когда отказываетесь хранить в каждом классе набор ссылок на другой класс. В VBA это приведет к утечке памяти, потому что сборщик мусора, основанный на подсчете ссылок, никогда не уничтожит объекты с циклическими ссылками, даже если группа, которую они образуют вместе, больше не нужна.
Но что, если вам действительно нужна такая двунаправленная связь?
Существуют разные решения для работы с циклическими ссылками с использованием разных методов. В VBA вам нужен механизм для освобождения перекрестных ссылок в каком-то месте, когда вы знаете, что они больше не нужны. Другими словами, вам нужно как-то управлять самим временем жизни ссылок.
Возможной реализацией может быть поддержка глобального словаря групп, которые активны. Когда вы хотите удалить группу, скажем, в какой-то процедуре, существующей где-то в коде, вы сначала освобождаете (очищаете) ее набор студентов. Это разорвет циклическую ссылку, позволяя сборщику мусора работать правильно. Ниже приведен скелет такой возможной реализации.
'In class clsUser:
Public id as String '<~~ could be any type of identifier, such as Integer
Public groups as New Dictionary
Public Sub subscribeToGroup(g as clsGroup)
Me.groups.add g.id, g
End Sub
Public Sub unsubscribeFromGroup(g as clsGroup)
Me.groups.Remove g.id
End Sub
''''''''''''''''''''''''''''''''''''''''''''''''
'In class clsGroup:
Public id as String '<~~ could be any type of identifier, such as Integer
Public users as New Dictionary
Public Sub registerUser(u as clsUser)
Me.users.add u.id, u
End Sub
Public Sub unregisterUser(u as clsUser)
Me.users.Remove u.id
End Sub
Public Sub removeAllUsers() 'empty the users collection, break the circular reference
For Each u In users: u.unsubscribeFromGroup(Me): Next
users.RemoveAll
End Sub
''''''''''''''''''''''''''''''''''''''''''''''''
У вас есть где-то (например, глобальная переменная или в каком-то классе с именем GroupManager и т. д.) словарь групп и методы для создания или удаления группы.
Public AllGroups as Dictionary
Function addGroup(id as String) as clsGroup
Set addGroup = new clsGroup
addGroup.id = id
AllGroups.Add id, addGroup
End Function
Sub removeGroup(g as clsGroup)
' Explicitly Tell the group to free its users before going away.
' This would not be needed if we didn't have circular references!
g.removeAllUsers
AllGroups.Remove g.id
End Sub
Теперь циклические ссылки исчезли, и группа будет уничтожена (без утечки памяти), потому что ничто не содержит ссылок на нее.
person
A.S.H
schedule
23.11.2015