2

プロパティ(Items:TItems)を持つクラス(TMyClass)があります

TItems = class;    

TMyClass = class(TComponent)
private
   FItems: TItems;
   procedure SetItems(const Value: TItems);
protected

public

protected
  property Items: TItems read FItems write SetItems;
end.

TExItems = class(TItems)
private
  FNewProb: Integer;
protected

public

published
  property NewProp: Integer read FNewProb write FNewProb;
end.

TExMyClass = class(TMyClass)
private
   FItems: TExItems;
   procedure SetItems(const Value: TItems);
protected

public

published
  property Items: TExItems read FItems write SetItems;
end.

新しい「Items」プロパティはTItemsから継承されますが、コンポーネントをインストールしたときに、「NewProb」であるTExItemsの新しいプロパティが表示されず、「Items」プロパティはまだTExItemsではなくTItemsであるように見えます...それをオーバーライドする方法?

ありがとう

変更:これが実際のコードです

タイプTKHAdvSmoothDock=class;

TKHAdvSmoothDockItem = class(TAdvSmoothDockItem)
private
  FImageIndex: TImageIndex;
  procedure SetImageIndex(const Value: TImageIndex);
protected

public

published
  property ImageIndex: TImageIndex read FImageIndex write SetImageIndex default -1;
end;

TKHAdvSmoothDockItems = class(TAdvSmoothDockItems)
private
  FOwner: TKHAdvSmoothDock;
  FOnChange: TNotifyEvent;
  function GetItem(Index: Integer): TKHAdvSmoothDockItem;
  procedure SetItem(Index: Integer; const Value: TKHAdvSmoothDockItem);
protected
  function GetOwner: TPersistent; override;
public
  constructor Create(AOwner: TKHAdvSmoothDock);
  function Add: TKHAdvSmoothDockItem;
  function Insert(Index: Integer): TKHAdvSmoothDockItem;
  property Items[Index: Integer]: TKHAdvSmoothDockItem read GetItem write SetItem; default;
  procedure Delete(Index: Integer);
published
  property OnChange: TNotifyEvent read FOnChange write FOnChange;
end;

TKHAdvSmoothDock = class(TAdvSmoothDock)
private
  FImageChangeLink: TChangeLink;
  FImages: TCustomImageList;
  FItems: TKHAdvSmoothDockItems;
  procedure ImageListChange(Sender: TObject);
  procedure SetImages(const Value: TCustomImageList);
  procedure SetItems(const Value: TKHAdvSmoothDockItems);
  function GetItems: TKHAdvSmoothDockItems;
  { Private declarations }
protected
  procedure UpdateImagesFromImageList;
public
  constructor Create(AOwner: TComponent); override;
  destructor Destroy; override;
published
  property Images: TCustomImageList read FImages write SetImages;
  property Items: TKHAdvSmoothDockItems read GetItems write SetItems;
end;

よろしく。

4

5 に答える 5

3

プロパティのゲッターとセッターは仮想であり、クラスを継承することでオーバーライドできます。更新された例については、以下を参照してください。サンプルコードには注意点が1つあります。それは、プロパティのタイプを変更しようとしていることです。これは許可されていません。チェックインすることをお勧めValue is TExItemsしますTExMyClass.SetItemsが、継承されたItemsプロパティを使用し、それ以降の継承者のすべてのメソッドでTExItemsにキャストしますTExMyClass

TItems = class;

TMyClass = class(TComponent)
private
   FItems: TItems;
   procedure SetItems(const Value: TItems); virtual;
protected
  property Items: TItems read FItems write SetItems;
end;

TExItems = class(TItems)
private
  FNewProb: Integer;
protected

public

published
  property NewProp: Integer read FNewProb write FNewProb;
end;

TExMyClass = class(TMyClass)
private
   procedure SetItems(const Value: TItems); override;
end;
于 2012-07-11T13:34:14.467 に答える
2

プロパティを仮想化することはできないため、オーバーライドすることはできません。それらは非表示にすることができます。つまり、のコンテキスト内では、へのTExMyClass参照Itemsは、祖先で宣言されたプロパティではなく、そのクラスで宣言されたプロパティに解決されます。

静的(宣言されたコンパイル時)型がTMyClassItemsあるものがある場合、実行時型が。であっても、常にそのクラスの型を参照しTExMyClassます。

SetItems基本クラスで保護された仮想として宣言し、同じ名前を持つまったく新しいプロパティを宣言する代わりに、子孫でそれをオーバーライドすることができます。

于 2012-07-11T13:29:04.967 に答える
1

技術的には、プロパティをオーバーライドすることはできませんが、いくつかの方法でオーバーライドを模倣することができます。最も基本的なマナーについては、たとえばこの回答を参照してください。

今、私はのコードを持っていないTAdvSmoothDockので、残りはただ推測しています。のプロパティgetterとsetterが仮想の場合、それらTAdvSmoothDock.Itemsをオーバーライドできます。しかし、より高度なコンポーネントでは、TMSのコンポーネントがそうであると思いますが、オーバーライドできる新しいアイテムが必要になるたびに呼び出される保護されたメソッドを持つ可能性が高くなります。その場合は、次のように実装する必要があります。TAdvSmoothDockCreateItem

function TKHAdvSmoothDock.CreateItem: TAdvSmoothDockItem;
begin
  Result := TKHAdvSmoothDockItem.Create;
end;

そしてそれを次のように使用します:

TKHAdvSmoothDockItem(AKHAdvSmoothDock.Items[I]).ImageIndex := ...
于 2012-07-11T15:44:22.023 に答える
1

getItemメソッドとsetItemメソッドを実装およびオーバーライドできます。

TMyClassに対してのみプロパティItemを実装します

property Items: TItems read getItems write setItemps;

TMyClassの場合:

public:  
function getItems : TItems; virtual;
procedure setItems(items: TItems); virtual;

TExMyClassの場合:

public:
function getItems : TItems; override;
procedure setItems(items: TItems); override;

function TExMyClass.getItems : TItems;
begin
  result := fItems;
end;

procedure TExMyClass.setItems(items : TItems);
begin
  self.itmes := items;
end;

したがって、TExMyClass.items.className = TExItems!

于 2012-07-11T14:00:22.213 に答える
0

同じLinesオブジェクトを使用する複数のTMemoを作成しようとするのと同じ問題です。

そのセクションにTCustomMemodelcaresがあるため、同じを使用するTMemoを複数持つことはできません。privateFLines: TStrings;FLines

TCustomMemo作業の唯一の方法(私はまだ知っています)は、クラス全体をとして完全に複製することですが、パブリックセクションでTLinkedCustomMemo定義します。FLines: TStrings;また、「TMemo」のクローンを作成する必要がありますが、参照する必要はありTLinkedCustomMemoません。TCustomMemo

次に、delcaringのハックを使用するTMemo=class(TLinkedMemo)と、にパブリックアクセスFLinesできるので、残りのすべてのリンクされたメモで、そのオブジェクトをメインのTMemoのオブジェクトに置き換えることができます。

なぜTMemosのコンテンツにそのようなリンクがあるのですか?簡単な答えは次のとおりです。同じテキストを表示する複数のTMemoを用意して、一部のスプレッドシートのように、ユーザーが一度に2つ(またはそれ以上)の異なる部分を表示(および編集)できるようにします。それら、水平スクロールバーの同期など。

時々とても簡単に見えることをする、それは本当にとても複雑です!VCL設計の欠陥が原因です。

TMemosのサンプルの場合...TStringsの内部​​にあるTStringListに基づいてLinesプロパティが定義されていないのはなぜですか?そうすれば、同じ文字列リストを同時に複数のTMemoに使用できます。

確認したい場合は、内部的にそのようなものにどのように依存しているかを確認してください...クラスを検索してくださいTMemoStrings(StdCtrlsの実装セクションに表示されます)。なぜそれは1つのTMemoだけを持たなければならないのですか?そしてなぜそれはまったく持っていなければならないのですか?どうしてそんな地獄の代わりにTStringListを使わなかったのですか?

一部のクラスが非常に閉じている場合...クラスを宣言するハッキング方法があります...しかし、一部のクラスを完全に複製する必要なしに、コントロールのプロパティのみを変更する方法(ほんの少しの変更)?

そうそう、コンテンツにリンクされたメモの実際のサンプルは次のようになります。

  • メモリストレージを2倍にすることなく、テキストファイルの2つの異なる部分を(同時に)ユーザーに表示させる
  • またはより良いサンプル:ユーザーは、スクロールせずに3行目と1000万行目の単語を編集したいと考えています。

したがって、2つのTMemoを配置し、Linesプロパティをリンクすると、ユーザーは、常に上下にスクロールしなくても、両方のメモからそのようなLinesプロパティを(異なるポイントで)編集するためのコントロールを使用できます。

別のサンプル:

  • ユーザーは、100万から100万プラス20行を編集したいが、同時に10から20行を表示する必要があります。
  • copy32ビットWindowsで3GiBを超えるRAM(許可されていません)を使用してメモを作成することはできません。各メモには、それぞれ1.6GiBを超えるRAMが必要です...など。
  • このようなデータを複製することはできません。ユーザーは2番目のメモを編集しますが、最初は同期している必要があります。フォーカスを緩めた後(または見栄えを良くしたい場合は編集直後)、すべてのデータを1つから他のメモにコピーする必要があります。 ..計算時間?-等

たくさんのサンプルがあります...そして最も重要なものは私が理解できないものです。

したがって、一般的な形式で質問に答えるには、「クラスをハックして少し変更する方法」:

  1. 新しいユニットでクラスを定義するコードのクローンを作成し、そのユニットを、いくつかの変更を加えてそのクラスのクローンを作成するためのものであることを明確にするものと呼びます。
  2. 変更が後方互換である場合にのみ同じクラス名を使用します(たとえば、TEdid the Alignプロパティに追加する場合は、それをとして宣言するハックを使用しますTTheClass=class(TheUnit.TTheClass))。それ以外の場合は、別の名前を使用します。
  3. セクションの最後usesにそのような新しいユニットを追加しますinterface

それは...言うのは簡単ですが、場合によっては大変な作業です。

Alignmentにプロパティを追加するサンプルを除いて、常にnesクラス名を使用することをお勧めしTEditます。

宣言のハックを使用するときは?完全なアプリケーションがすでにコーディングされていて、そのすべてに配置を追加したいTEdit場合...新しいコンポーネントを作成し、それをコンポーネントツールに追加し、すべてのフォームを再定義して使用:TEdit; および使用しないようにします:TMyAlignedEdit...単純に追加できますユニットと出来上がりを使用するには...すべてTEditにそのようなプロパティがあり、IDEインスペクターもそれを確認します。

于 2017-04-24T10:01:01.253 に答える