Вопрос, поднятый пользователем, заключается в необходимости уведомления класса сущности TEntity об удалении связанного с ним элемента сетки TMesh. Для решения этой задачи необходимо реализовать механизм, который позволит вызвать метод OnMeshRemove класса TEntity из деструктора класса TMesh.
Решение проблемы
Шаг 1: Регистрация сущности в сетке
Класс TEntity должен зарегистрировать себя в сетке TMesh, чтобы при уничтожении сетки получить уведомление.
Шаг 2: Уведомление при удалении
Создадим в классе TMesh список объектов, которые будут уведомлены о его удалении.
constructor TBaseClass.Create;
begin
inherited;
FNotificationList := TList<TBaseClass>.Create;
end;
destructor TBaseClass.Destroy;
var
AClass: TBaseClass;
begin
if Assigned(FNotificationList) then
begin
if FNotificationList.Count > 0 then
for AClass in FNotificationList do
AClass.Notify(Self);
FNotificationList.Free;
FNotificationList := nil;
end;
inherited;
end;
procedure TBaseClass.Notify(AClass: TBaseClass);
begin
end;
procedure TBaseClass.RegisterForNotification(AClass: TBaseClass);
begin
if not Assigned(AClass) then
Exit;
if FNotificationList.IndexOf(AClass) < 0 then
FNotificationList.Add(AClass);
end;
procedure TBaseClass.UnregisterNotification(AClass: TBaseClass);
begin
if not Assigned(AClass) then
Exit;
if FNotificationList.IndexOf(AClass) >= 0 then
FNotificationList.Remove(AClass);
end;
procedure TEntity.Notify(AClass: TBaseClass);
begin
inherited;
// Обработка уведомления об удалении сетки
FMesh := nil;
DoMeshRemoved;
end;
procedure TEntity.DoMeshRemoved;
begin
if Assigned(FOnMeshRemoved) then
FOnMeshRemoved(Self);
end;
procedure TEntity.SetMesh(Value: TMesh);
begin
if Assigned(FMesh) then
begin
FMesh.UnregisterNotification(Self);
FMesh := nil;
end;
if Assigned(Value) then
begin
FMesh := Value;
FMesh.RegisterForNotification(Self);
end;
end;
Шаг 4: Переопределение деструктора для TMesh
destructor TMesh.Destroy;
begin
if Assigned(FEntityContainer) then
FEntityContainer.UnregisterNotification(FEntityContainer);
inherited;
end;
Подтвержденный ответ
Для упрощения кода и уменьшения количества операций с указателями, можно использовать следующий подход:
type
TEntity = class
public
Mesh: TMesh;
constructor Create;
destructor Destroy; override;
end;
constructor TEntity.Create;
begin
inherited Create;
Mesh := TMesh.Create;
Mesh.EntityContainer := Self;
end;
destructor TEntity.Destroy;
begin
if Mesh <> nil then
begin
Mesh.EntityContainer := nil;
FreeAndNil(Mesh);
end;
inherited Destroy;
end;
type
TMesh = class
EntityContainer: TObject;
destructor Destroy; override;
end;
destructor TMesh.Destroy;
begin
if (EntityContainer <> nil) and (TEntity(EntityContainer).Mesh = Self) then
TEntity(EntityContainer).Mesh := nil;
EntityContainer := nil;
inherited Destroy;
end;
В данном примере, при уничтожении объекта TMesh, он проверяет, что ссылка на TEntity не является nil, и если это связанный объект, то ссылка на TMesh в TEntity обнуляется, что предотвращает обращение к освобожденному объекту.
Альтернативный ответ
Если TMesh является коллекцией элементов TEntity, то можно использовать TCollection и TCollectionItem для управления связями между объектами. Это позволит использовать встроенные механизмы уведомлений.
Заключение
В данной статье мы рассмотрели, как можно уведомить класс сущности TEntity об удалении связанного с ним элемента сетки TMesh в Delphi. Мы предложили два варианта решения: использование списка уведомлений и прямое взаимодействие между объектами. Выбор метода зависит от конкретной ситуации и требований к проекту.
Уведомление класса сущности о необходимости обновления своих ссылок и возможных обработчиков событий в связи с удалением элемента сетки, к которому он был привязан.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.