将字段和方法添加到 class 继承自同一基而不修改基 class 的元素
Add Fields and Methods to classes that inherit from same base without modifying base class
在我的应用程序中,我需要向第 3 方控件添加一些额外的功能。
例如 TcxLabel 和 TcxDBLabel(来自 DevExpress)。
两者都继承自相同的基础 class.
对于那些控件,我想添加一些字段和方法。
我今天的做法:
TMycxLabel = class(TcxLabel)
private
FMyField1: string;
FMyField2: Integer;
public
procedure DoSomething;
end;
TMycxDBLabel = class(TcxDBLabel)
private
FMyField1: string;
FMyField2: Integer;
public
procedure DoSomething;
end;
所以基本上我必须把所有的东西都写两次。
实现它的一种方法是修改基础 class 这 2 个控件继承自。
但这不是一个选项 - DevExpress classses / packages 不应该被修改。
有没有办法添加实现这个?
您能否继承一次虚拟 class(即 "yours"),在那里定义新字段,然后从那里继承两个新的 classes?
根据评论编辑:
好吧,你可以这样试试。
在你继承的 classes 中,只需添加一个 public 数据成员,它本身就是一个 class,你可以在其中定义你自己的东西......看起来像:
TMycxLabel = class(TcxLabel)
public
MyStuff: TMyStuff;
end;
TMyStuff = class()
private
FMyField1: string;
FMyField2: Integer;
public
procedure DoSomething;
end;
然后像
那样称呼它
cxLabel1.MyStuff.DoSomething();
我意识到这并不能完全回答您的问题,并且不适用于几个用例(您不能通过这种方式从 MyStuff 访问 TMycxLabel 的所有属性),但也许您可以避免一些双重编码。
Is there a way to add achieve this?
不,没有。任何可行的解决方案都将基本上等同于您当前的方法。由于您需要与实例关联的状态,因此您实际上需要它成为实例的一部分。这会引导您找到现有的解决方案。
您可以考虑劫持 Tag
之类的字段来存储该状态,但这是错误的,因为 Tag
保留供该类型的使用者使用。其他可能的解决方案可能涉及维护一个单独的列表,该列表将实例映射到此附加状态。你可以让它工作,但在我看来,它太笨重了,以至于比替代方案更糟糕。
最有效的方法是将字段添加到公共基础class,但您已经排除了这种可能性,因为它涉及修改第三方代码。
有一种方法,但只有当您只需要基础 class 中可用的内容时它才会起作用。
例如,如果 TcxDBLabel 继承自 TcxLabel,则只要您只使用 TcxDBLabel 的 TcxLabel 部分(字段、方法和属性),就可以为两者添加一个方法(松散地说)。
我指的是类型转换。
我应该警告,这种做法的使用并非自愿的。许多开发人员认为 typecasting 是一种不好的做法,而我本人倾向于将其用作最后的手段。但是,我会把关于天气的哲学讨论留给你,你应该或不应该使用它。
因此,如果您像这样创建子class:
THcxLabel = Class(TcxLabel)
private
FMyField1: string;
FMyField2: Integer;
public
procedure DoSomething;
End;
然后您可以将其添加到任何基于 TcxLabel 的 class 实例,如下所示:
THcxLabel(cxLabel1).DoSomething;
THcxLabel(cxDBLabel1).DoSomething;
就像我说的,在 DoSomething 方法中您无法使用 TcxDBLabel 的任何细节,但您将能够使用基础 class 资源。
在我的应用程序中,我需要向第 3 方控件添加一些额外的功能。
例如 TcxLabel 和 TcxDBLabel(来自 DevExpress)。 两者都继承自相同的基础 class.
对于那些控件,我想添加一些字段和方法。
我今天的做法:
TMycxLabel = class(TcxLabel)
private
FMyField1: string;
FMyField2: Integer;
public
procedure DoSomething;
end;
TMycxDBLabel = class(TcxDBLabel)
private
FMyField1: string;
FMyField2: Integer;
public
procedure DoSomething;
end;
所以基本上我必须把所有的东西都写两次。
实现它的一种方法是修改基础 class 这 2 个控件继承自。 但这不是一个选项 - DevExpress classses / packages 不应该被修改。
有没有办法添加实现这个?
您能否继承一次虚拟 class(即 "yours"),在那里定义新字段,然后从那里继承两个新的 classes?
根据评论编辑:
好吧,你可以这样试试。
在你继承的 classes 中,只需添加一个 public 数据成员,它本身就是一个 class,你可以在其中定义你自己的东西......看起来像:
TMycxLabel = class(TcxLabel)
public
MyStuff: TMyStuff;
end;
TMyStuff = class()
private
FMyField1: string;
FMyField2: Integer;
public
procedure DoSomething;
end;
然后像
那样称呼它cxLabel1.MyStuff.DoSomething();
我意识到这并不能完全回答您的问题,并且不适用于几个用例(您不能通过这种方式从 MyStuff 访问 TMycxLabel 的所有属性),但也许您可以避免一些双重编码。
Is there a way to add achieve this?
不,没有。任何可行的解决方案都将基本上等同于您当前的方法。由于您需要与实例关联的状态,因此您实际上需要它成为实例的一部分。这会引导您找到现有的解决方案。
您可以考虑劫持 Tag
之类的字段来存储该状态,但这是错误的,因为 Tag
保留供该类型的使用者使用。其他可能的解决方案可能涉及维护一个单独的列表,该列表将实例映射到此附加状态。你可以让它工作,但在我看来,它太笨重了,以至于比替代方案更糟糕。
最有效的方法是将字段添加到公共基础class,但您已经排除了这种可能性,因为它涉及修改第三方代码。
有一种方法,但只有当您只需要基础 class 中可用的内容时它才会起作用。 例如,如果 TcxDBLabel 继承自 TcxLabel,则只要您只使用 TcxDBLabel 的 TcxLabel 部分(字段、方法和属性),就可以为两者添加一个方法(松散地说)。
我指的是类型转换。
我应该警告,这种做法的使用并非自愿的。许多开发人员认为 typecasting 是一种不好的做法,而我本人倾向于将其用作最后的手段。但是,我会把关于天气的哲学讨论留给你,你应该或不应该使用它。
因此,如果您像这样创建子class:
THcxLabel = Class(TcxLabel)
private
FMyField1: string;
FMyField2: Integer;
public
procedure DoSomething;
End;
然后您可以将其添加到任何基于 TcxLabel 的 class 实例,如下所示:
THcxLabel(cxLabel1).DoSomething;
THcxLabel(cxDBLabel1).DoSomething;
就像我说的,在 DoSomething 方法中您无法使用 TcxDBLabel 的任何细节,但您将能够使用基础 class 资源。