Поздравляю, вы открыли для себя COM. Верее, тот факт, что объекты в Delphi частью своей внутренней структуры (по положительному смещению от указателя) соответствуют формату COM-объектов.
Автоматический вызов AddRef/Release как раз и сделан для полного соответствия COM-механизмам и невозбранного использования Delphi-объектов как объектов COM. Для того же, для чего и структура соответствует
ну то что вызов AddRef/Release сделан для облечения взаимодействия с COM — согласен. Но повторюсь — соответствия формата структуры дельфийского IInterface и комовского IUnknown для работоспособности моего кода не требуется.
Хотя для _старших_ версий дельфи есть вариант писать:
begin
MyObj := TMyObj.Create;
MyObj.DoWork();
end; // тут объект будет уничтожен
но на мой взгляд — это неочевидное решение. В коде как то должно быть обозначено, что объект сам разрушется. В моем варианте вызов CreateObjectDestroyer — явное указание на это
Я боюсь напутать за давностью лет :)
Если в самом классе реализовать интерфейс, он тоже будет автоматически уничтожатся.
Кажется в каком-то парсере XML это реализовано. Конечно, это не подойдет для существующих классов.
>>Если в самом классе реализовать интерфейс, он тоже будет автоматически уничтожатся.
О, это тоже тонкий момент, все зависит от того, как этот класс использовать
var
Obj: TInterfacedObject; // реализатор IUnknown
begin
Obj := TInterfacedObject.Create;
end // Obj — не уничтожится. Будет мем лик.
в данном примере нету присвоений объекта к интерфейсной ссылке, поэтому не будет вызваны AddRef/Release, счетчик ссылок не работает и мы имеем грабли.
Так много уже где делают. Например, в JVCL работа с классами-контейнерами построена полностью на интерфейсах. Ну и, конечно, c MSXML тоже удобнее работать через интерфейсы, но там все-таки COM…
Я делал синтаксис with Using(MyObject, TMyObject.Create) do… а-ля C#. Причем можно и просто Using — кому как понятнее. Тем не менее для команды не покатило — плохо читалось другими разработчиками.
Зачем? Какой смысл в этом? Неужели так сложно запомнить «создал — освободи». Смысл в этом диком нечитабельном огороде, который лишь засоряет чистейший эфир кода?
try/except обертка вокруг (из примера «как делали до меня») — это вообще не красиво. Долой exception'ы!
Указанный вами подход упоминается на delphi-сайтах года с 2000 точно, в том или ином исполнении.
Интересно. Я что то похожее давно пытался сделать, но не прижилось. Не из-за указанных недостатков. Просто для одних действий мне проще сделать with TClass.Create do try DoWorck finally Free; end; а в основном делаю интерфейс и работаю с объектом через него. Да и случаи когда надо локально создавать и освобождать объект не так часто встречаются.
Конечно это напоминает COM, тут и фабрика класса и реализация интерфейса на основании подсчета количества ссылок, но реально под задачу описанную в примере — подсчет ссылок не нужен. Нужен аналог С++ шаблона (извините, не помню есть ли такое в делфи — 100 лет в делфи не программил), т.е. некий класс который сам создаваясь на стеке создает экземпляр нужного нам объекта в куче. Когда первый объект вылетит из зоны видимости, он сам будет уничтожаться (он ведь в стеке) ну и в деструкторе должен потянуть за собой уничтожение объекта из кучи.
Подсчет ссылок нужен тогда, когда мы совсем отпускаем объект в свободное плавание, передаем его в разные функции, маршалим его между потоками и т.п. тут он уничтожается неявно когда становится не нужен. И тут возникает как раз проблема создания фабрики классов и автоматического удаления, чтобы и операция создания и операция удаления была сделана одним и тем же рантаймом.
Дельфи. Автоматическое уничтожение объектов по выходу из метода