Этот код Delphi покажет утечку памяти для экземпляра TMyImplementation:
program LeakTest;
uses
Classes;
type
MyInterface = interface
end;
TMyImplementation = class(TComponent, MyInterface)
end;
TMyContainer = class(TObject)
private
FInt: MyInterface;
public
property Impl: MyInterface read FInt write FInt;
end;
var
C: TMyContainer;
begin
ReportMemoryLeaksOnShutdown := True;
C := TMyContainer.Create;
C.Impl := TMyImplementation.Create(nil);
C.Free;
end.
Если TComponent заменяется TInterfacedObject и конструктором, измененным для Создания (), утечка исчезает. Что отличается с TComponent здесь?
Большое спасибо за ответы. Подвести итог: это легко, но неправильно, для высказывания, "Если Вы используете интерфейсы они - считаемая ссылка, и следовательно они освобождены для Вас". - На самом деле любой класс, который реализует интерфейс, может нарушить это правило. (И не будет никакой подсказки компилятора или предупреждения быть показанными.)
TComponent._release
не бесплатно ваш экземпляр. TINTERFACESOBJECT._RELEASE
делает бесплатное ваш экземпляр. Возможно, кто-то может быть, но мой взять на себя так, это то, что TComponent
не предназначен для использования в качестве ссылки, подсчитанного объекта, как мы обычно используют интерфейсы.
function TComponent._Release: Integer;
begin
if FVCLComObject = nil then
Result := -1 // -1 indicates no reference counting is taking place
else
Result := IVCLComObject(FVCLComObject)._Release;
end;
Предполагается, что компонент должен быть принадлежен и уничтожен чем-то другим, как правило, является формой. В этом сценарии ссылочный счет не используется. Если вы проходите компонент в качестве ссылки на интерфейс, было бы очень неудачно, если бы он был уничтожен, когда метод возвращается.
Следовательно, отсчет ссылок в TComponent был удален.
Нет, нет лучшего способа сделать это. Однако я не думаю, что это имеет большое значение. Код уже упакован как повторно используемый метод. Если необходимо использовать его из нескольких отдельных классов, просто превратитесь в публичный статический метод в каком-нибудь служебном классе.
Как только вы это сделаете, для всех практических целей у вас будет удобный способ преобразования ab-массива объектов в массив классов. Другими словами, если вы уже внедрили определенный сервис в многоразовом пути, то вы эффективно расширили набор инструментов. Не имеет значения, что эта конкретная услуга не является частью «стандартной» JRE.
-121--4817695-Насколько мне известно, ВЫ НЕ МОЖЕТЕ. CSS относится к стилю, а изображение src - к содержимому.
-121--1896641-TComponent не реализует свои методы _AddRef и _Release так же, как и TInterfacedObject. Он откладывает отсчет ссылок на свое свойство VCLComObject , которое должно быть одним другим объектом с интерфейсом . Так как TComponent не подсчитывает ссылки, он не может определить, когда количество ссылок достигает нуля, поэтому он не освобождается.
Свойство VCLComObject содержит ссылку на интерфейс, которая должна реализовывать IVCLComObject . Если связанному с компонентом объекту VCLComObject было указано, что ему принадлежит компонент, то при достижении нулевого количества ссылок на этот интерфейс он уничтожит связанный с ним компонент. Ему сказали, что он владеет компонентом, вызвав его метод FreeOnRelease.
Все это предназначено для упрощения преобразования компонентов VCL в COM-объекты. Если это не ваша цель, то вы, вероятно, будете бороться с несколькими другими неожиданными аспектами дизайна на этом пути, так что вы, возможно, захотите пересмотреть мотивацию для того, чтобы ваши компоненты реализовывали интерфейсы в первую очередь.