![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Как узнать количество экземпляров класса?
@!!ex © (2008-07-09 15:26:00)Суть задачи:
Есть класс TMyClass.
У него есть ID.
В конструкторе надо ID менять. так, чтобы первому созданному экземпляру ставилось 1, второму - 2, и так далее.
Причем светчик должен быть уникальным для класса. Тоесть если мы делаем наследника, то наследник должен иметь свой счетчик. Как это лучше всего сделать?
Palladin (2008-07-10 13:00:00) [1]у TObject есть замечательный метод ClassType:TClass, результатом которого является класс который инстанцируется, если стоит задача считать экземпляры, то есть смысл создать общего родителя классов со счетчиками и считать до потери пульса, бо self.classtype вернет именно тот класс который инстанцируется, далее осталось лишь реализовать класс-карту, объект которого и будет возвращать тот самый счетчик для определенного значения ClassType которое есть уникально для всего приложения
Тын-Дын (2008-07-10 01:44:00) [2]
> @!!ex © (09.07.08 16:28) [12]
>
> > [6] Dennis I. Komarov © (09.07.08 15:56)
>
> 6. в данном случае это лишь для того, чтобы соблюсти уникальность
> имен.
Тогда вообще в чем проблема?
type
TMyClass=class
private
FId: Integer;
public
constructor Create;
end;
var
GlobalId: Integer=0;
implementation
{ TMyClass }
constructor TMyClass.Create;
begin
FId := InterLockedIncrement(GlobalId);
end;
oxffff (2008-07-09 21:51:00) [3]
> @!!ex © (09.07.08 15:26)
Перекрыть Newinstance и изучить исходники реализации dynamic методов в Delphi для .NET. И сделать аналогично.
Поросенок Винни-Пух (2008-07-09 18:24:00) [4]А кто-то здесь упоминал дубовые решения
han_malign (2008-07-09 18:16:00) [5]где-то примерно так
_TfakeClassCount = class
protected
procedure _falkeCOunter; virtual;
end;
TfakeClassCount = class(_TfakeClassCount)
private
procedure _falkeCOunter; override;//hide method
protected
function _GetCounter: Pointer;
end;
function TfakeClassCount._GetCounter: Pointer;
asm
mov EAX, [EAX]//get VMT address
lea [EAX+ VMTOFFSET _TfakeClassCount._falkeCOunter]//get VMT entry address
end;
............
... PDWORD(_GetCounter)^ ...
@!!ex (2008-07-09 17:58:00) [6]> - зарезервировать место в VMT виртуальным методом-заглушкой
> и использовать для хранения счетчика/маски...
А как это сделать??
> только, если наследник не перекроет ни одного виртуального
> метода родителя - счетчик/маска будет родительским(новый
> VMT не будет создан)...
Это невозможно. Наследник обязательно перекрывает кучу методов, иначе он нафиг не нужен.
han_malign (2008-07-09 17:52:00) [7]
> Причем светчик должен быть уникальным для класса.
- зарезервировать место в VMT виртуальным методом-заглушкой и использовать для хранения счетчика/маски... только, если наследник не перекроет ни одного виртуального метода родителя - счетчик/маска будет родительским(новый VMT не будет создан)...
Kolan (2008-07-09 16:54:00) [8]> А можно не добавлять в юзез модуль наследника там где нужны
> наследники?
Можно. При реализации Паладина вообще ничего ненадо добавлять:
Пример упрощен.
1. Модуль А, тут описаны классы.
Общий предок такой:
TCustom = class
function GetInstanciesCount: Integer;
end;
И наследник, допустим такой:
TDescendant = class(TCustom)
end;
2. Допустим имеем фасад/синглетон, модуль B:
uses A
TFacade = class
function GetObject: TDescendant
end;
3. И еще модуль С, использующий фасад:
uses B
...
begin
ShowMessage(IntToStr(TFacade.GetInstance.GetObject.GetInstanciesCount));
end;
Kolan (2008-07-09 16:46:00) [9]> с головой хватит конструтора и деструктора
Влучае иерархии с несколькими корневыми классами, то есть, когда несколько иерархий, придётся дублировать. А в фабрике всеравно останется один вызов.
Хотя, я не настаиваю, можно и так и эток. Можно вообще имена по счётчики инкрементировать или каждый раз GUID генерить, и вообще без подсчёта обойтись.
Поросенок Винни-Пух (2008-07-09 16:43:00) [10]Кроме того, придется добавлять видимость модуля везде где нужны счётчики.
А можно не добавлять в юзез модуль наследника там где нужны наследники?
Kolan (2008-07-09 16:41:00) [11]> Сделал около каждого наследника в модуле счетчик, в итоге
> при создании наследника приходится позаботиться об имени,
> но это не такая уж и проблема.
Имхо, плохое решение. При добавлении наследников придётся добавлять и счётчик. Кроме того, придется добавлять видимость модуля везде где нужны счётчики.
Palladin (2008-07-09 16:38:00) [12]
> Кто-то должен вести подсчёт. Логично, что удобнее всего
> это делать при создании и удалении.
с головой хватит конструтора и деструктора
Kolan (2008-07-09 16:37:00) [13]> обоснуй
Кто-то должен вести подсчёт. Логично, что удобнее всего это делать при создании и удалении. Фабрики и нужны для того, что бы создавать объекты.
Можно, напрмер, сделать так:
Obj := Factory.CreateObject;
try
Obj.ThisIsMyUnitedStatesOfWhatEver;
finally
Factory.Utilize(Obj);
end;
То есть получать объекты с фабрики и сдавать их обратно в утиль :). А фабрика пусть считает.
> Типа как в дельфи, когда на форму кидаешь кнопку, у нее
> автоматически имя имеет порядковый номер. для уникальности.
> Задача стоит в точности такая же. Создание визуального редактора.
Дык и пользуй этот дэлфаевский готовый метод, GetUniqueName называется, или как-то так?
@!!ex (2008-07-09 16:28:00) [14]> [6] Dennis I. Komarov © (09.07.08 15:56)
6. в данном случае это лишь для того, чтобы соблюсти уникальность имен.
Типа как в дельфи, когда на форму кидаешь кнопку, у нее автоматически имя имеет порядковый номер. для уникальности.
Задача стоит в точности такая же. Создание визуального редактора.
Сделал около каждого наследника в модуле счетчик, в итоге при создании наследника приходится позаботиться об имени, но это не такая уж и проблема.
Palladin (2008-07-09 16:28:00) [15]обоснуй
Kolan (2008-07-09 16:26:00) [16]Может использовать классовые методы?
Вообще, конечно, нужен ответственный за инстанцирование, то есть фабрика.
Palladin (2008-07-09 16:08:00) [17]
> Поросенок Винни-Пух © (09.07.08 15:58) [7]
звиняюсь... непросек... но решение дубовое
реально хватит в родителе
Inc(CountersMap[Class]);
и можешь в наследниках забыть о каких либо счетчика
Palladin (2008-07-09 16:06:00) [18]
> Поросенок Винни-Пух © (09.07.08 15:58) [7]
а зачем нам при создании наследника еще и родителя счетик накручивать?
Поросенок Винни-Пух (2008-07-09 15:58:00) [19]constructor CreateIt(AOwner : TComponent; BIncrement : boolean);
begin
inherited Create(AOwner);
if BIncrement then Inc(fCounterA);
end;
constructor DescendantCreateIt(AOwner : TComponent; BIncrement : boolean);
begin
inherited CreateIt(AOwner, False);
if BIncrement then Inc(fCounterB);
end;
Dennis I. Komarov (2008-07-09 15:56:00) [20]> [0] @!!ex © (09.07.08 15:26)
А если сделали 1, 2, 3, 4, 5, потом убили 3, следующий создавать какой?