TCollection のコンストラクタには TComponent は必要ありませんが、TCollectionItemClass は必要です。
コレクションがコンポーネントの直接のメンバーではなく、TPersistent プロパティのメンバーになったことは、コンストラクターにとって何の違いもありません。
アップデート
異なるのは所有権ですが、次に TPersistent レベルで、次の正しい実装によって管理する必要がありますGetOwner
。
GetOwner は、オブジェクトの所有者を返します。GetOwner は、永続オブジェクトの所有者を見つけるために GetNamePath メソッドによって使用されます。GetNamePath と GetOwner が TPersistent に導入されたため、コレクションなどの子孫をオブジェクト インスペクタに表示できます。
TCollection プロパティが TPersistent プロパティによって所有されており、TPersistent プロパティがコンポーネントによって所有されていることを IDE に伝える必要があります。
使用しているチュートリアルには、この実装に関するいくつかのエラーがあります。
- コレクションの所有者は、TPersistent である必要がある TComponent として宣言されます。
- TPersistent プロパティ クラスには GetOwner が実装されていません。
- チュートリアルの最後に示されている、TPersistent プロパティは代わりに TComponent から継承する必要があると述べている修正は、明らかに間違っています。またはもっとうまく言えば、GetOwner を実装しないための回避策です。
これは次のようになります。
unit MyComponent;
interface
uses
Classes, SysUtils;
type
TMyCollectionItem = class(TCollectionItem)
private
FStringProp: String;
protected
function GetDisplayName: String; override;
public
procedure Assign(Source: TPersistent); override;
published
property StringProp: String read FStringProp write FStringProp;
end;
TMyCollection = class(TCollection)
private
FOwner: TPersistent;
function GetItem(Index: Integer): TMyCollectionItem;
procedure SetItem(Index: Integer; Value: TMyCollectionItem);
protected
function GetOwner: TPersistent; override;
public
constructor Create(AOwner: TPersistent);
function Add: TMyCollectionItem;
function Insert(Index: Integer): TMyCollectionItem;
property Items[Index: Integer]: TMyCollectionItem read GetItem
write SetItem;
end;
TMyPersistent = class(TPersistent)
private
FOwner: TPersistent;
FCollectionProp: TMyCollection;
procedure SetCollectionProp(Value: TMyCollection);
protected
function GetOwner: TPersistent; override;
public
procedure Assign(Source: TPersistent); override;
constructor Create(AOwner: TPersistent);
destructor Destroy; override;
published
property CollectionProp: TMyCollection read FCollectionProp
write SetCollectionProp;
end;
TMyComponent = class(TComponent)
private
FPersistentProp: TMyPersistent;
procedure SetPersistentProp(Value: TMyPersistent);
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
published
property PersistentProp: TMyPersistent read FPersistentProp
write SetPersistentProp;
end;
procedure Register;
implementation
procedure Register;
begin
RegisterComponents('Samples', [TMyComponent]);
end;
{ TMyCollectionItem }
procedure TMyCollectionItem.Assign(Source: TPersistent);
begin
if Source is TMyCollectionItem then
FStringProp := TMyCollectionItem(Source).FStringProp
else
inherited Assign(Source);
end;
function TMyCollectionItem.GetDisplayName: String;
begin
Result := Format('Item %d',[Index]);
end;
{ TMyCollection }
function TMyCollection.Add: TMyCollectionItem;
begin
Result := TMyCollectionItem(inherited Add);
end;
constructor TMyCollection.Create(AOwner: TPersistent);
begin
inherited Create(TMyCollectionItem);
FOwner := AOwner;
end;
function TMyCollection.GetItem(Index: Integer): TMyCollectionItem;
begin
Result := TMyCollectionItem(inherited GetItem(Index));
end;
function TMyCollection.GetOwner: TPersistent;
begin
Result := FOwner;
end;
function TMyCollection.Insert(Index: Integer): TMyCollectionItem;
begin
Result := TMyCollectionItem(inherited Insert(Index));
end;
procedure TMyCollection.SetItem(Index: Integer; Value: TMyCollectionItem);
begin
inherited SetItem(Index, Value);
end;
{ TMyPersistent }
procedure TMyPersistent.Assign(Source: TPersistent);
begin
if Source is TMyPersistent then
CollectionProp := TMyPersistent(Source).FCollectionProp
else
inherited Assign(Source);
end;
constructor TMyPersistent.Create(AOwner: TPersistent);
begin
inherited Create;
FOwner := AOwner;
FCollectionProp := TMyCollection.Create(Self);
end;
destructor TMyPersistent.Destroy;
begin
FCollectionProp.Free;
inherited Destroy;
end;
function TMyPersistent.GetOwner: TPersistent;
begin
Result := FOwner;
end;
procedure TMyPersistent.SetCollectionProp(Value: TMyCollection);
begin
FCollectionProp.Assign(Value);
end;
{ TMyComponent }
constructor TMyComponent.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FPersistentProp := TMyPersistent.Create(Self);
end;
destructor TMyComponent.Destroy;
begin
FPersistentProp.Free;
inherited Destroy;
end;
procedure TMyComponent.SetPersistentProp(Value: TMyPersistent);
begin
FPersistentProp.Assign(Value);
end;
end.
TOwnedCollection
しかし、TMyCollection の使用と宣言がはるかに簡単になるから継承することもできます。
TMyCollection = class(TOwnedCollection)
private
function GetItem(Index: Integer): TMyCollectionItem;
procedure SetItem(Index: Integer; Value: TMyCollectionItem);
public
function Add: TMyCollectionItem;
function Insert(Index: Integer): TMyCollectionItem;
property Items[Index: Integer]: TMyCollectionItem read GetItem
write SetItem;
end;