Как указать, что мой класс является владельцем объекта, который он создает?

Я пытаюсь определить класс, который будет иметь общедоступное ADOConnection, которое может установить другое приложение.

Однако я не могу заставить конструктор работать над созданием переменной ADOConnection. Это код, который у меня есть до сих пор:

unit SuperheroClass;

interface

uses
  ADODB;

type
  TSuperhero = Class

  private
    MyQry: TADOQuery;
    constructor Create;
  public
    MyCon: TADOConnection;

end;

implementation

constructor TSuperhero.Create;
begin
  MyCon := TADOConnection.Create(self);
end;

end.

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

Этот код дает мне ошибку:

[Ошибка] SuperheroClass.pas(23): несовместимые типы: «TComponent» и «TSuperhero».

Что я здесь делаю неправильно?


person user1685639    schedule 07.10.2013    source источник


Ответы (2)


Вы можете объявить TSuperhero = Class(TComponent).

Предок TComponent может владеть и управлять другими компонентами

Также убедитесь, что ваш Constructor общедоступен, если вы хотите, чтобы он был виден другим устройствам. то есть:

public 
  constructor Create(AOwner: TComponent); override;

...

constructor TSuperhero.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  // TSuperhero.Self now owns MyCon and responsible for freeing it
  MyCon := TADOConnection.Create(Self); 
end;

Если Superhero требуется во всем приложении, я бы создал экземпляр TSuperhero, например:

Superhero := TSuperhero.Create(Application);

И пусть Application будет владельцем Superhero и ответственным за его освобождение.


Просто чтобы добавить к моему ответу, использование вашего класса TSuperhero очень похоже на TDataModule (TComponent), поэтому, возможно, вам стоит использовать централизованный TDataModule — добавьте к нему TADOConnection и т. д. и используйте этот экземпляр в своем приложении.

person kobik    schedule 07.10.2013
comment
Спасибо, это имеет смысл для меня. Я хочу предотвратить утечку памяти самостоятельно. - person user1685639; 07.10.2013
comment
Я не вижу необходимости добавлять сюда дополнительные накладные расходы. Соединение можно просто создать, используя nil как Owner, если код в деструкторе также освобождает его. Это одна дополнительная строка кода в деструкторе, которая так же эффективно предотвращает утечку памяти, добавляя эту единственную строку кода. - person Ken White; 07.10.2013
comment
@KenWhite, я думал, что вопрос был конкретно о том, как явно создать MyCon := TADOConnection.Create(Self) с Self в качестве владельца. Это также полезно, если вы хотите создать TSuperhero с формой в качестве владельца и не беспокоиться об освобождении экземпляра вручную. - person kobik; 07.10.2013
comment
Я читал это: мне нужно создать эти внутренние переменные класса, используя себя, чтобы они принадлежали классу, а затем я могу освободить их в деструкторе класса. Либо нет необходимости использовать Self (что правильно, если вам не нужны дополнительные функциональные возможности и накладные расходы TComponent) и использовать деструктор для его освобождения, либо использовать TComponent и Self, и в этом случае деструктор не нужен. чтобы освободить его. Я не вижу ничего в вопросе, который требует дополнительных накладных расходов TComponent на данный момент. (Обратите внимание, я не минусовал, а просто прокомментировал.) - person Ken White; 07.10.2013
comment
@KenWhite, прочитав вопрос ОП снова (и снова), я попросил его не принимать мой ответ, так как я также считаю, что TComponent не требуется. лично я бы выбрал TComponent с Application в качестве его владельца просто потому, что я предпочитаю делать Superhero := TSuperhero.Create(Application) при запуске и забыть о Superhero... - person kobik; 07.10.2013
comment
А также TSuperhero предназначен для использования очень похоже на TDataModule (TComponent). Так что, возможно, TDataModule - действительно правильный путь... :) - person kobik; 07.10.2013
comment
Я никогда не предлагал удалить его (и даже не говорил, что это неправильно — как я уже сказал, я не минусовал его). Я просто указал, что нет необходимости добавлять поддержку во время разработки, интеграцию с IDE, потоковую передачу и накладные расходы на поддержку COM, если они здесь не нужны. (Добавление TComponent сопряжено со значительными накладными расходами; я предпочитаю не использовать его, если он действительно не нужен. - person Ken White; 07.10.2013
comment
@kobik Ваш ответ - это то, что я хотел. Я не уверен, как реализовать класс как TDataModule. И это также будет происходить от TComponent, так что в чем преимущества? Я хочу максимально придерживаться ООП. Кроме того, пользователь этого класса создаст экземпляр объекта TSuperhero, а затем передаст объекту ADOConnection в качестве параметра. Надеюсь, это поможет. - person user1685639; 08.10.2013
comment
@ user1685639, вам не нужно реализовывать класс как новый TDataModule. Вы просто используете TDataModule. то есть: Файл->Создать->Модуль данных. посмотрите здесь - person kobik; 08.10.2013

Вы можете передать nil в качестве параметра TADOConnection.Create. Это не мешает вам уничтожить его в деструкторе класса TSuperHero.

constructor TSuperhero.Create;
begin
  MyCon := TADOConnection.Create(nil);
end;

Параметр, передаваемый конструктору TADOConnection, используется, когда элемент управления перетаскивается на форму как визуальный компонент. Вы получаете ошибку компиляции в своем коде, потому что TSuperHero не происходит от TComponent.

person Keith Miller    schedule 07.10.2013
comment
Я добавил MyCon := TADOConnection.Create(nil); и сейчас ошибок нет. - person user1685639; 07.10.2013
comment
Должен ли я все еще объявлять TSuperhero из TComponent, как это предлагает kobik? - person user1685639; 07.10.2013
comment
Вы можете, но в этом нет необходимости, если только вам не нужны дополнительные функциональные возможности, которые предоставляет вам TComponent. Если вы решите пойти по этому пути, вы можете использовать self в конструкторе параметров, как и в исходном вопросе. - person Keith Miller; 07.10.2013
comment
Пожалуйста, не забудьте принять ответы на вопросы, которые вы задаете. См. stackoverflow.com/help/accepted-answer. - person Keith Miller; 07.10.2013
comment
Если вы создаете компонент с помощью .Create(nil), вы также должны сами освободить объект, если он вам больше не нужен. Скорее всего в деструкторе FreeAndNil(MyCon); - person fuchs777; 07.10.2013
comment
Наследуйтесь от TComponent только в том случае, если вы действительно хотите сделать его компонентом (то есть чем-то, что вы можете добавить в форму в IDE). В противном случае не поленитесь и разрушьте то, что вы создали. - person Stefan Glienke; 07.10.2013
comment
Долгое время я защищал pov как у вас. Но после самостоятельной разработки некоторых компонентов я изменил свой подход: если мне нужно управлять более чем 1 (или максимум 2) подобъектами, я наследую от TComponent, даже если он не попадет в палитру. Если бы у TObject или TPersistent было право собственности, я бы, конечно, использовал его. - person Fabricio Araujo; 07.10.2013