如何在不更改父项的情况下从子项中删除继承的对象

Ave*_*yne 5 forms oop erp subclassing

(注意:更改名称以保护有罪)

因此,假设我正在对VisualCruft 8进行修改(早已被供应商停止),并将这些修改应用于"公司A"的ERP软件(很久以后被"公司S"收购,然后他们停止了一些软件多年后,由于VisualCruft自行停产).

我经常需要做的一个修改是向表单添加,更改或删除字段.这是大多数ERP软件的基础,每年都会出现几次.我们的ERP软件包的布局,我们将其称为"HotPockets版本3",将表单划分为"类库",而这些类库只是用于保存表单对象的桶.当然,"形式"中嵌入了"控制"对象.

每次安装HotPockets 3时,您都会获得表单的系统版本,以及单独的类库中的子版本,它只是父类的重新类,因此表单,控件,业务逻辑等都存在在孩子身上 原始("公司A")供应商声明的意图是允许您对覆盖父级的子进行更改,同时允许所述供应商向父级发布补丁/更改/任何内容.理论上这看起来很棒.在实践中,存在问题.具体来说,当在父级中定义控件本身并且不更改父级时,如何删除或更改表单上的控件?目的是用具有不同行为的不同控件替换控件,尽管在某些情况下我还必须完全删除控件.所以,您也可以将其称为"如何在不改变父项的情况下从子项中删除继承的对象"?

有一些已知的解决方案,但我问这个问题,因为我想看看是否有比我提供的更好的答案. 为避免重复答案,我将列出当前已知的解决方案,但请记住,我正在寻找此处未列出的内容.

解决方案不当1

虽然我不应该修改父代,但我确实可以访问父代码.我可以简单地记下所讨论的控件的所有属性和方法,从父级删除控件,然后返回到子级并重新实现所有属性和方法.对于大幅度的更改,例如用某个网格替换单个文本框,这是可行的.然而,它完全"违反规则",并且为此产品提供支持的VAR有点皱眉(注意:VAR不是"公司A"或"公司S").请记住,不仅原始供应商已经解散,而且产品和语言也已不复存在.

解决方案不当2

"隐藏"父窗体上的组件,然后(如果合并新组件)将新更改添加到子窗体.这在实践中听起来很棒,直到你意识到所有旧代码都挂钩到了父代,现在......它是隐形的.这意味着重命名父组件的版本,并通过解决方案1中列出的所有"端口属性和方法".在这种情况下......为什么我要再次这样做?

解决方案不当3

对于那些我希望控件消失的情况,我可以通过设置visibility属性来隐藏子控件.这不会删除或更改任何现有代码,一切都会继续运行.然而,绑定到它的控件和数据库字段现在"捆绑"并且不可用,除非我查看解决方案1或解决方案2之类的东西,因为任何试图弄乱控件的操作都可能在调用期间导致副作用,和/或以编程方式替换控件下面的数据使用户无法观察发生的情况.而这只能解决视觉上消失的控制问题- 它并没有解决它的问题.

极不正确的解决方案4

该死的鱼雷,从父母那里删除控制,全力以赴!

显然,这是一个非常糟糕的决定......

你会注意到所有的解决方案都涉及触摸父母,这是我不应该做的事情 - 这使我们完整地回答了这个问题.

其他解决方案不可用

  • 用其他东西替换HotPockets版本3.这不是我决策的范畴.

  • 使用(在此处插入喜欢的宠物语言)重写我需要的HotPockets版本3.虽然我不介意这样做 - 我确实拥有像大多数人一样的自己的宠物语言 - 但这不是一种可能性,因为VisualCruft几乎与它本身一起工作.相信我,这比在VisualWidget 3.14159HeyDoYouSmellCoffee甚至ILikeSnakes中编写扩展所需的努力大10倍,找出某种跨语言调用,集成它,测试它,让IT管理人员注销它,让VAR也签署它,而不是只是坚持使用VisualCruft中的本机工具.

  • 让VAR做到这一点.不要采取错误的方式,VAR做得很好,提供持续的支持,并提供了许多有用的修改.但是有成本因素可以发挥作用,如果变化是由我而不是VAR进行的,那么它更具成本效益.这根本与他们无关.

Mar*_*ser 3

首先我要说的是,从我的角度来看,要快速了解你的问题并不是那么容易。

每次安装 HotPockets 3 时,您都会获得表单的系统版本,以及单独类库中的子版本,该子版本只是父级的重新类,以便表单、控件、业务逻辑等全部存在在孩子身上。正如原始(“公司 A”)供应商所述,其目的是允许您对覆盖父级的子级进行更改,同时允许所述供应商向父级发布补丁/更改/任何内容。从理论上讲,这看起来很棒。在实践中,存在一些问题。

>In theory this looks great.
Run Code Online (Sandbox Code Playgroud)

不,不是的!继承是两个实体(也称为类)可以拥有的最牢固的关系。这就是为什么 Gamma 在 1994 年提出了它,并得到了广泛的认同:

赞成委托而不是继承!

委托比继承更加解耦。例如,在您的情况下,您可以为客户自定义表单字段创建一个键值存储。

然而,从你的问题来看,我不清楚这样的改变是否在你的职责范围内。但这就是你所描述的所有“邪恶”的根源。


在我的印象中,在你的问题中,你混淆了设计时类结构中的父子关系和运行时对象结构的树状类组合的父子结构。

这样想:您的类是文件和文件夹,文件夹可以包含文件...通过这种方式,您可以在运行时创建任意树状结构。这称为“组合设计模式”。如果您不知道这一点,您会在网上获得大量信息。


最后在你的赏金范围内你提议

这是 OOP 范式的限制。

恕我直言,事实并非如此——由于明显滥用继承,这是设计中的一个严重缺陷。

回到你的问题:

如何在不更改父对象的情况下从子对象中删除继承的对象?

  1. 在设计时还是在运行时?(您不能在运行时更改继承)
  2. 在设计时完全删除继承。