Перейти к содержанию
Fire Monkey от А до Я
  • 0

Определить, к какому TObjectList принадлежит элемент


Alex7wrt

Вопрос

Добрый день

Столкнулся с такой задачей:

Существует несколько TObjectList<TRectangle>. При создании каждого из них  AOwnsObjects задано как True. 

RectList[i]:=TObjectList<TRectangle>.Create(True);
............
Nrect:=TRectangle.Create(nil);
Nrect.Parent:=Form1;
RectList[i].Add(Nrect);

Существует ли способ определить, к какому из  TObjectList принадлежит элемент

Ссылка на комментарий

Рекомендуемые сообщения

  • 0

Вряд ли. Списков может быть очень много. Нужно у каждого спрашивать, есть ли в нем нужный объект? Есть ли способ у самого объекта получить ссылку на тот ObjectList, к которому он принадлежит?

Ссылка на комментарий
  • 0

При создании TRectangle - нужно указывать кто Owner - владелец, вместо nil.

У каждого Rectangle Owner и будет нужный класс TObjectList .

И вообще нужно всегда указывать Owner - ведь TObjectList отвечает за их уничтожение, это основная фича владельцев.

Я недавно баг поймал с фреймом - если при создании TFrame указать Owner nil - то на фрейме не будет работать анимация TFloatAnimation . Так что TFrame.Create(Self формы) - все заработало.

Изменено пользователем ENERGY
Ссылка на комментарий
  • 0

Ваш пример с фреймом немного из другой оперы,  поскольку TObjectList нельзя указать в качестве Owner. Это список, а не комонент, иначе все было бы гораздо проще.

А для управления жизненным циклом обьектов как раз и установлен в True параметр AOwnsObjects.

Изменено пользователем Alex7wrt
Ссылка на комментарий
  • 1
5 часов назад, Alex7wrt сказал:

 

Существует ли способ определить, к какому из  TObjectList принадлежит элемент

Пишите в TagObject элемента  экземпляр TObjectList ! И все!

Ссылка на комментарий
  • 0
1 минуту назад, wamaco сказал:

Пишите в TagObject элемента  экземпляр TObjectList ! И все!

Да, такой подход допустим, его рассматривал среди прочего. Но хочется узнать, есть ли более "прямолинейный подход" в FMX.

Ссылка на комментарий
  • 0

 

47 минут назад, Alex7wrt сказал:

Ваш пример с фреймом немного из другой оперы,  поскольку TObjectList нельзя указать в качестве Owner. Это список, а не комонент, иначе все было бы гораздо проще.

А для управления жизненным циклом обьектов как раз и установлен в True параметр AOwnsObjects.

Согласен, я только добрался до компа. Owner TComponent, а TObjectList <T> дженерик, а не обычный TObjectList еще больше усложняет. Как вытащить дженерик из указателя я не курсе, с обычным TObjectList это просто, но это уже другой вопрос.

Изменено пользователем ENERGY
Ссылка на комментарий
  • 0
8 часов назад, Alex7wrt сказал:

уществует ли способ определить, к какому из  TObjectList принадлежит элемент

нет. Потому что элемент не принадлежит никакому листу.

Это список знает, что при удалении элемента нужно сделать ему Free / заNil-ить ссылку на элемент. Только список.

Сам объект (элемент списка) не подозревает о том, что он кому-то там "принадлежит".

Ссылка на комментарий
  • 0
1 час назад, kami сказал:

Можно это обойти (и довольно неплохо, не костыльно)... но это нужно кодить. Готового механизма  нет.

Самый простой и быстрый вариант уже указали - TagObject, здесь самое сложное это вытащить из указателя дженерик класс. Я не знаю возможно ли это вообще, т.к. встречал на стэке инфу о том что никак.

Самый простой вариант использовать классический TObjectList, НЕ дженерик тогда вытащить ссылку из TagObject просто  - TagObject is TObjectList,  TagObject as TObjectList или TObjectList(TagObject).

Если нужно отличать один TObjectList от другого, я бы отнаследовался от него и сделал свой метод Add где устанавливал бы в Rect ссылку на список, там же можно добавить функцию для определения ID списка из Rect, а также ввел какой то идентификатор для списка. 

Изменено пользователем ENERGY
Ссылка на комментарий
  • 1
8 часов назад, ENERGY сказал:

самое сложное это вытащить из указателя дженерик класс.

В рантайме нет никаких дженериков. Компилятор преобразует все дженерики в реальные списки с необходимой типизацией. Поэтому - действительно никак. Вполне возможно, что даже is TObjectList<TMyClass> не сработает - компилятор вполне вправе посчитать исходный класс TObjectList<TMyClass> не тем, с которым производится is.

8 часов назад, ENERGY сказал:

я бы отнаследовался от него и сделал свой метод Add

Это неправильно. Потому что есть еще Insert, есть Update (в том числе - и InsertRange). Правильно - перекрыть метод Notify или реализовать обработчик события OnNotify (последнее даже создания наследников не требует).

Вообще, если по каким-то причинам необходимо знать "владельца", было бы совсем хорошо сделать наследника от TRectangle, который будет реализовывать интерфейс наподобие такого:
 

IOwneredIntf = interface
    ['{ADF563F3-B4CE-4E96-9559-F0FFC2936D5Z}']
    function GetOwner: TObject;
    procedure SetOwner(const Value: TObject);

    property Owner: TObject read GetOwner write SetOwner;
  end;

Список, который хочет установить владельческие отношения с этим TRectangle, в своем методе Notify приводит его к интерфейсу и устанавливает intf.Owner:=Self

Ну и в обратном порядке - тоже.

При этом появляется возможность работать со списком не только TRectangle, а вообще чем угодно, что поддерживает указанный интерфейс.

И если список сделать тоже с поддержкой интерфейса (не знаю, какие методы в нем необходимы), то и сам объект может работать со своим владельцем абсолютно не интересуясь его типом.

Ссылка на комментарий
  • 1
  • Администраторы

Если честно, тут задача на мой взгляд в неправильном подходе. Который порождает странную задачу. Это как плыть против течения, вместо того, чтобы плыть по течению.

Если требуется выполнить данную задачу, то  лучше не побояться написать один дополнительный класс "Менеджер объектов", которому вы будите делегировать данную задачу.

Чтобы поиск был быстрый, нужно использовать словарь. Время поиска будет O(1) против поиска в списке. Один из вариантов реализации может быть таким:

  1. В менеджере есть набор ваших списков (логические группы объектов) - список списков
  2. В менеджере есть словарь соответствия контрол -> индекс списка из (1)
  3. при добавлении контрола добавляете его в список и заносите контрол в словарь
  4. Поиск за О(1)

Вариант, который предложил Kami хороший для вариантов, когда объекты ваши. А вот если вы хотите для штатных контролов это сделать, то чтобы подмешать такой интерфейс, вам потребуется сделать наследников для каждого UI контрола. А если эти контролы еще и на форме лежат, то там придется изрядно попотеть, чтобы добавить в IDE ваши версии штатных контролов с этим интерфейсом.

P.S. Избегайте паттерна один контрол "владеется" несколькими списками. Это к "При создании каждого из них  AOwnsObjects задано как True.". Такой подход рано или поздно при усложнии логики закончится AV и сложным дебаггингом, кто кого удалил и когда и почему. Используйте золотое правило: "Один объект может иметь только одного владельца, один объект может использовать во многих других местах. Только владелец отвечает удаление объекта и в хорошем случае и за его создание. Клиенты объекта только пользуются им и не удаляют его."

Ссылка на комментарий
  • 0
  • Администраторы
13 минут назад, krapotkin сказал:

золотые слова )

мне лень было столько букв писать ))) 

Грех не написать подробный ответ нашему постоянному пользователю с времен зарождения форума :)

Ссылка на комментарий
  • 0
5 часов назад, Brovin Yaroslav сказал:

Чтобы поиск был быстрый, нужно использовать словарь. Время поиска будет O(1) против поиска в списке. Один из вариантов реализации может быть таким:

  1. В менеджере есть набор ваших списков (логические группы объектов) - список списков
  2. В менеджере есть словарь соответствия контрол -> индекс списка из (1)
  3. при добавлении контрола добавляете его в список и заносите контрол в словарь
  4. Поиск за О(1)

Проще использовать бинарный поиск для поиска своего индекса-идентификатора контрола, готовый бинарный поиск реализован в TList и его потомках, также в массивах.

Изменено пользователем ENERGY
Ссылка на комментарий
  • 0
  • Администраторы

Если я все помню, то поиск в не упорядоченном списке Бинарным поиском - это O(nlog(n)). А поиск в словаре О(1).

Ссылка на комментарий
  • 0
Только что, Brovin Yaroslav сказал:

Если я все помню, то поиск в не упорядоченном списке Бинарным поиском - это O(nlog(n)). А поиск в словаре О(1).

Но ведь  еще нужно время чтобы в словаре найти сответствие.

Ссылка на комментарий

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить на вопрос...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...