How to override an inherited property?
Solution 1
Property getters and setters can be virtual, and then overridden by inheriting classes, see below for your example updated. There's one caveat with you're example code and that's you're trying to change the type of the property, which is not allowed. I would advise you check for Value is TExItems
in TExMyClass.SetItems
but use the inherited Items property and cast to TExItems in all methods of TExMyClass
and further inheritants.
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;
Solution 2
Properties cannot be virtual, so they cannot be overridden. They can be hidden, in that within the context of TExMyClass
, references to Items
will resolve to the property declared in that class, not the one declared in the ancestor.
If you have something whose static (declared, compile-time) type is TMyClass
, Items
will always refer to the one from that class, even if its run-time type is TExMyClass
.
You could declare SetItems
as protected and virtual in the base class, and then override it in the descendant instead of declaring a whole new property that happens to have the same name.
Solution 3
You can implement and override methods getItem and setItem;
Implement property Item only for TMyClass
property Items: TItems read getItems write setItemps;
For TMyClass:
public:
function getItems : TItems; virtual;
procedure setItems(items: TItems); virtual;
For 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;
so, TExMyClass.items.className = TExItems !
Solution 4
Technically, you can't override a property, but you can mimic override in several ways. See for example this answer for the most basic manners.
Now I do not have the code for TAdvSmoothDock
so the rest is just guessing. When the property getter and setter of TAdvSmoothDock.Items
are virtual, you could override them. But in more advanced components, and I suppose the ones from TMS are, then there is a good chance of TAdvSmoothDock
having a protected CreateItem
method which is called whenever there is need of a new item which could be overriden. If that is the case, then you should implement it like:
function TKHAdvSmoothDock.CreateItem: TAdvSmoothDockItem;
begin
Result := TKHAdvSmoothDockItem.Create;
end;
And use it like:
TKHAdvSmoothDockItem(AKHAdvSmoothDock.Items[I]).ImageIndex := ...
user1512094
Updated on June 04, 2022Comments
-
user1512094 almost 2 years
I have a class (TMyClass) which have a property (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.
The new "Items" property is inherited from TItems but when I installed the component the new property of TExItems which is "NewProb" did not appear and it looks like the "Items" property is still TItems not TExItems...how to override it?
Thanks
Modification : Here is the Real code
type 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;
Regards.
-
user1512094 almost 12 yearsThanks for this great reply but in the TExMyClass Class the Setter procedure "SetItems" takes Value from TItems...I want it to take TExItems ? when I changed its (Value parameter) type from TItems to TExItems the compiler gave me the following error : [DCC Error] xxxxxx.pas(34): E2037 Declaration of 'SetItems' differs from previous declaration how to fix this error?
-
Stijn Sanders almost 12 yearsLike I said, changing the property type when inheriting is not allowed. Checking the type when setting and using
Items as TExItems
should work though. -
user1512094 almost 12 yearsThank you very much for the example! it is very important to read such examples before working with properties.... I was searching and I found something maybe i would help me but i need more explanation here is my question : cannot I use the "reintroduce" instead of "Override"? for the setter and getter?
-
NGLN almost 12 yearsYou could, but it is a bad idea because it would break inheritance: i.e. when the ancestor calls the setter or getter, yours wouldn't be called.
-
thewaywewere almost 7 yearsWelcome to SO!. Your reply does not look like a good answer to the question. Once you have sufficient reputation you will be able to comment on any post. Also check this what can I do instead.
-
Franco Michel Almeida Caixeta about 3 yearsA good solution, but if the parent class is in units other than the daughter, the virtual property and the override must be in protected to work.