Delphi 如何覆盖继承的属性?
我有一个类(TMyClass),它有一个属性(Items:TItems) 新的“Items”属性是从TItems继承的,但是当我安装组件时,TExItems的新属性“NewProb”没有出现,看起来“Items”属性仍然是TItems而不是TExItems…如何覆盖它 谢谢 修改: 这是真正的代码 类型 TKHAdvSmoothDock=类Delphi 如何覆盖继承的属性?,delphi,inheritance,properties,overriding,Delphi,Inheritance,Properties,Overriding,我有一个类(TMyClass),它有一个属性(Items:TItems) 新的“Items”属性是从TItems继承的,但是当我安装组件时,TExItems的新属性“NewProb”没有出现,看起来“Items”属性仍然是TItems而不是TExItems…如何覆盖它 谢谢 修改: 这是真正的代码 类型 TKHAdvSmoothDock=类 TKHAdvSmoothDockItem = class(TAdvSmoothDockItem) private FImageIndex: TImage
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;
注意。属性不能是虚拟的,因此不能重写它们。它们可以隐藏,因为在
TExMyClass
的上下文中,对项的引用将解析为在该类中声明的属性,而不是在祖先中声明的属性
如果某个对象的静态(声明的,编译时)类型为TMyClass
,Items
将始终引用该类中的对象,即使其运行时类型为TExMyClass
您可以在基类中将SetItems
声明为受保护和虚拟,然后在子体中重写它,而不是声明一个恰好具有相同名称的全新属性。属性getter和setter可以是虚拟的,然后通过继承类重写,请参见下面更新的示例。您的示例代码有一个警告,那就是您试图更改属性的类型,这是不允许的。我建议您在TExMyClass.SetItems
中检查值是否为TExItems
,但在TExMyClass
的所有方法中使用继承的Items属性并强制转换为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;
您可以实现和覆盖getItem和setItem方法
仅为TMyClass实现属性项
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 从技术上讲,您不能重写属性,但可以通过几种方式模拟重写。有关最基本的礼仪,请参见示例
现在我没有TAdvSmoothDock
的代码,所以剩下的只是猜测。当TAdvSmoothDock.Items
的属性getter和setter是虚拟的时,您可以重写它们。但是在更高级的组件中,我认为TMS中的那些是,那么就有很大的机会TAdvSmoothDock
拥有一个受保护的CreateItem
方法,每当需要一个可以被覆盖的新项时就会调用该方法。如果是这种情况,那么您应该像这样实施它:
function TKHAdvSmoothDock.CreateItem: TAdvSmoothDockItem;
begin
Result := TKHAdvSmoothDockItem.Create;
end;
然后像这样使用它:
TKHAdvSmoothDockItem(AKHAdvSmoothDock.Items[I]).ImageIndex := ...
这与尝试使用同一Lines对象的多个TMemo的问题相同
由于TCustomMemo
delcares在其private
部分FLines:TStrings代码>不可能有多个TMemo使用相同的FLines
工作的唯一方法(我仍然知道)是将整个TCustomMemo
类完全复制为TLinkedCustomMemo
,但定义FLines:TStrings代码>在公共部分;还需要克隆“TMemo”,但引用的是TLinkedCustomMemo
,而不是TCustomMemo
然后使用delcarcingTMemo=class(TLinkedMemo)
的破解,您将拥有对FLines
的公共访问权限,因此您可以在所有其余链接的备忘录上用主TMemo的对象替换该对象
为什么在TMemos的内容上会有这样的链接?
简单的答案可能是:有多个TMemo显示相同的文本,这样用户可以一次看到(和编辑)两个(或更多)不同的部分,就像一些电子表格一样。。。它通常还包括它们之间的水平拆分器、同步水平滚动条等
有时候做一些看起来很简单的事情,其实很复杂!
只是因为VCL设计有问题
对于TMemos的示例。。。为什么它们没有被定义为基于TStringList插入TStrings的Lines属性?这样,我们可以同时对多个TMemo使用相同的字符串列表
如果要看,内部是如何依赖于这样的。。。搜索类TMemoStrings
(它出现在StdCtrls的实现部分)。为什么它必须只有一个TMemo?,为什么它必须有?为什么不用TStringList来代替那些该死的东西呢
当某些课程关闭时。。。它来自于声明类的黑客方式。。。但是,如何只更改控件的一个属性而不需要完全复制某些类(只是为了更改这么小的内容)
哦,是的,内容链接备忘录的实际示例可能是:
- 让用户(同时)看到文本文件的两个不同部分,而无需双倍的内存存储
- 或者更好的示例:用户希望在第3行编辑一个单词,在第1000万行编辑另一个单词,而无需滚动
因此,您可以放置两个TMemo并链接Lines属性,这样用户就可以从两个备忘录中编辑这样的Lines属性(在不同的点上),而无需一直上下滚动
另一个样本:
- 用户想要编辑一百万到一百万行加上二十行,但需要同时看到十到二十行
- 必须使用
复制的备忘录是不可能的,32位窗口上的内存超过3GiB(不允许),每个备忘录需要>1.6GiB的RAM。。。等等
- 复制这样的数据既不是一个选项,用户编辑第二个备忘录,但第一个必须同步。。。所以在散焦之后(或者编辑之后,如果你想好看的话),你必须把一张备忘录中的所有数据复制到另一张备忘录中。。。计算时间?
-等
有这么多的样品。。。最重要的是我想不出来的
因此,以一般形式回答您的问题,“如何对类进行黑客攻击以稍微修改它”:
克隆在一个新单元中定义类的代码,将该单元称为某种东西,以明确它是为了在经过一些修改后克隆该类
TKHAdvSmoothDockItem(AKHAdvSmoothDock.Items[I]).ImageIndex := ...