Карта сайта Kansoftware
НОВОСТИУСЛУГИРЕШЕНИЯКОНТАКТЫ
KANSoftWare

Уведомление класса сущности об удалении связанного с ним элемента сетки в Delphi

Delphi , Синтаксис , Память и Указатели

Вопрос, поднятый пользователем, заключается в необходимости уведомления класса сущности TEntity об удалении связанного с ним элемента сетки TMesh. Для решения этой задачи необходимо реализовать механизм, который позволит вызвать метод OnMeshRemove класса TEntity из деструктора класса TMesh.

Решение проблемы

Шаг 1: Регистрация сущности в сетке

Класс TEntity должен зарегистрировать себя в сетке TMesh, чтобы при уничтожении сетки получить уведомление.

Шаг 2: Уведомление при удалении

Создадим в классе TMesh список объектов, которые будут уведомлены о его удалении.

type
  TBaseClass = class
  private
    FNotificationList: TList<TBaseClass>;
  protected
    procedure Notify(AClass: TBaseClass); virtual;
  public
    procedure RegisterForNotification(AClass: TBaseClass);
    procedure UnregisterNotification(AClass: TBaseClass);
    constructor Create;
    destructor Destroy; override;
  end;

  TMesh = class(TBaseClass)
  private
    FEntityContainer: TEntity;
  public
    property EntityContainer: TEntity read FEntityContainer write FEntityContainer;
  end;

  TEntity = class(TBaseClass)
  private
    FMesh: TMesh;
    FOnMeshRemoved: TNotifyEvent;
    procedure SetMesh(Value: TMesh);
  public
    constructor Create;
    destructor Destroy; override;
    property Mesh: TMesh read FMesh write SetMesh;
    property OnMeshRemoved: TNotifyEvent read FOnMeshRemoved write FOnMeshRemoved;
  end;

Шаг 3: Реализация уведомлений

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




Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.


:: Главная :: Память и Указатели ::


реклама


©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007
Top.Mail.Ru

Время компиляции файла: 2024-12-22 20:14:06
2025-07-26 19:28:01/0.0059120655059814/0