我有一个类(TMyClass),它有一个属性(Items:TItems)
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但是当我安装组件时,TExItems的新属性“NewProb”没有出现,看起来“Items”属性仍然是TItems而不是TExItems ...如何覆盖它?
由于
修改: 这是真实代码
型 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;
问候。
答案 0 :(得分:1)
属性不能是虚拟的,因此无法覆盖它们。它们可以隐藏,因为在TExMyClass
的上下文中,对Items
的引用将解析为在该类中声明的属性,而不是在祖先中声明的属性。 / p>
如果您的静态(声明的,编译时)类型为TMyClass
,Items
将始终引用该类中的那个,即使其运行时类型为{{1 }}
您可以在基类中将TExMyClass
声明为protected和virtual,然后在后代中覆盖它,而不是声明一个恰好具有相同名称的全新属性。
答案 1 :(得分:1)
属性getter和setter可以是虚拟的,然后通过继承类来覆盖,请参阅下面的示例更新。有一个警告,你是示例代码,那是你试图改变属性的类型,这是不允许的。我建议您检查Value is TExItems
中的TExMyClass.SetItems
,但使用继承的Items属性并在TExMyClass
的所有方法和其他继承者中强制转换为TExItems。
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;
答案 2 :(得分:1)
您可以实现和覆盖方法getItem和setItem;
仅为TMyClass
实现属性Itemproperty 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!
答案 3 :(得分:1)
从技术上讲,您无法覆盖属性,但可以通过多种方式模仿覆盖。例如,请参阅this answer以获取最基本的方式。
现在我没有TAdvSmoothDock
的代码,所以剩下的只是猜测。如果TAdvSmoothDock.Items
的属性获取器和设置器是虚拟的,则可以覆盖它们。但是在更高级的组件中,我认为来自TMS的组件是,那么TAdvSmoothDock
很可能有一个受保护的CreateItem
方法,只要需要一个新的项目就可以调用它。覆盖。如果是这种情况,那么你应该像:
function TKHAdvSmoothDock.CreateItem: TAdvSmoothDockItem;
begin
Result := TKHAdvSmoothDockItem.Create;
end;
并使用它:
TKHAdvSmoothDockItem(AKHAdvSmoothDock.Items[I]).ImageIndex := ...
答案 4 :(得分:0)
与尝试使用多个使用相同Lines对象的TMemo的问题相同。
自TCustomMemo
private
部分FLines: TStrings;
FLines
以来,不可能有多个使用相同TCustomMemo
的TMemo。
工作的唯一方法(我仍然知道)是将整个TLinkedCustomMemo
课程完全复制为FLines: TStrings;
,但在公共部分定义TLinkedCustomMemo
;还需要克隆'TMemo'但引用TCustomMemo
,而不是TMemo=class(TLinkedMemo)
然后使用delcaring FLines
的hack,您将可以公开访问TMemoStrings
,因此您可以在所有其他链接的备忘录上用主TMemo的对象替换该对象。
为什么关于TMemos内容的链接? 简单的答案可能是:有多个TMemo显示相同的文本,因此用户可以一次看到(和编辑)两个(或更多)不同的部分,就像一些SpreadSheets那样...它通常还涉及一个水平分割器之间它们,同步水平滚动条等。
有时做一些看起来很容易的事情,实在太复杂了! 只是由VCL设计错误引起的。
对于TMemos的样本......为什么他们还没有根据TStrings的TStringList insead定义它的Lines属性?这样我们就可以同时为多个TMemo使用相同的字符串列表。
如果想看,内部如何依赖于这样......搜索类copy
(它出现在StdCtrls的实现部分)。为什么它必须只有一个TMemo?为什么它必须有?为什么不使用TStringList而不是所有地狱呢?
当某些类如此封闭时...它是以声明类的黑客方式...但是如何只更改控件的属性而不需要完全复制某些类(只是为了改变这么少的东西)? / p>
哦,是的,内容链接备忘录的真实样本可能是:
因此,您放置两个TMemo并链接Lines属性,因此用户可以使用控件在两个备忘录中编辑此类Lines属性(在不同点上),而无需一直向下滚动。
另一个样本:
TTheClass=class(TheUnit.TTheClass)
的备忘录,超过32位Windows上的3GiB RAM(不允许),每个备忘录需要> 1.6GiB的内存......等等。有很多样本......最重要的是我无法想象的样本。
以一般形式回答你的问题,“如何破解课程来修改它”:
uses
的hack),否则使用不同的名称interface
部分Alignment
就是这样......简单地说,在某些情况下要努力工作。
我总是建议使用nes类名称,除了将TEdit
属性添加到TEdit
的示例之外。
什么时候使用声明的黑客?如果您已经编码了一个完整的应用程序,并想要添加到其上的所有:TEdit;
,那么对齐...不是创建新组件,而是将其添加到组件工具,重新定义所有表单以不使用:TMyAlignedEdit
并使用TEdit
...您可以简单地添加以使用您的单位和瞧...所有{{1}}现在都有这样的属性,IDE inspertor也会看到它等等。