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

时间:2014-07-01 23:12:28

标签: forms oop subclassing erp

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

所以,让我们说我正在对VisualCruft 8进行修改(早已被供应商停止),并将这些修改应用于"公司A" (早已被"公司S"买了,几年后由于VisualCruft自行停产而停止使用该软件。)

我经常需要做的一项修改是向表单添加,更改或删除字段。这是大多数ERP软件的基础,每年都会出现几次。我们的ERP软件包的布局,我们称之为" HotPockets版本3",将表单分成"类库"反过来只是用来保持表格对象的桶;当然,还有"控制"嵌入在"表格中的对象"。

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

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

不正确的解决方案1 ​​

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

不正确的解决方案2

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

不正确的解决方案3

对于我希望控件消失的那些实例,我可以通过设置visibility属性来隐藏子控件。这不会删除或更改任何现有代码,一切都会继续运行。但是,绑定到它的控件和数据库字段现在已经被绑定了#34;除非我查看解决方案1或解决方案2之类的内容,否则不可用,因为任何试图弄乱控件都可能在调用期间导致副作用,和/或以编程方式替换控件下面的数据使用户无法观察到什么是发生。这只会解决控件在视觉上消失 - 它不会解决它的问题。

极不正确的解决方案4

该死的鱼雷,从父母那里删除控制,全速前进!

显然,这是非常错误的决定......

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

其他解决方案不可用

  • 将HotPockets版本3替换为其他内容。这不是我决策的范畴。

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

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

2 个答案:

答案 0 :(得分:3)

首先让我说,从我的观点来看,快速得到你的问题并不容易。

  

每次安装HotPockets 3都会得到系统版本的   表单,以及一个单独的类库中的子版本   重新设置父类,使表单,控件,业务逻辑,   等等都存在于孩子身上。意图,如所述   原始(“公司A”)供应商,是允许您进行更改的   覆盖父级的子级,同时允许所述供应商发布   补丁/更改/任何进入父级的内容。理论上这看起来很棒。   在实践中,存在问题。

>In theory this looks great.

不,不!继承是两个实体(也就是类)可以拥有的最强关系。这就是Gamma于1994年提出的原因,人们普遍认为:

赞成委托而不是继承!

委托与继承相比更加分离。就你的情况而言,您可以为客户自定义表单字段创建键值存储。

但是,从您的问题来看,我不清楚这种变化是否属于您的责任范围。 但这是你所描述的所有“邪恶”的来源。

<小时/> 进一步根据我的印象,在你的问题中,你在设计时混合了类结构中的父子关系,以及在运行时对象结构的树状类组合的父子结构。

以这种方式思考:您的类是文件和文件夹,文件夹可以包含文件......通过这种方式,您可以在运行时创建任意树状结构。这被称为“组合设计模式”。如果您不了解它,您将在网上获得大量信息。

<小时/> 最后,在你的赏金中,你提出了

  

这是OOP范式的限制   

恕我直言,它不是 - 由于明显滥用继承,这是设计中的一个严重缺陷。

回到你的问题:

  

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

  1. 在设计时或运行时? (您无法在运行时更改继承)
  2. 在设计时完全删除继承。

答案 1 :(得分:2)

问题“如何删除子项的继承成员”本身是不正确的。我实际上知道你在这种背景下的意思。但是,你对这个问题的措辞基本上是在问一些不可能的事情。如果要创建父子,is-a,两种类型之间的继承链,则假设一个是另一个的更专用形式。如果你认为人类有朝一日可能会发展到与“动物”没有任何共同之处,那么你就不应该从“动物”中继承“人类”。让我们记住,继承是在类之间进行耦合的。

我认为马丁在说明这不是OOP范式的限制时是正确的。当然,“Hot Pocket”设计人员知道当用户为子类使用继承时,他们应该能够做什么类型的修改。他们肯定想“允许”某些变化并“禁止”某些其他变化。例如,他们希望您能够更改控件的行为但无法将其删除。

话虽如此,如果你不同意并且相信添加或删除控件肯定是“Hot Pocket”设计师想到的东西,那么他们也应该为你提供一种方法来做到这一点。

总而言之,有三种可能的情况:

-A“Hot Pocket”设计师实际上为您提供了实现目标的方法    这(显然不会在这里引起你的问题)。

-B“Hot Pocket”设计师搞砸了。他们没有用户可能需要的线索    删除子类中的控件。

-C“Hot Pocket”设计师知道    他们在做什么。他们不希望您能够添加或删除控件    对于孩子的形式。

在案例A)中,我们已经有了解决方案。就像“热门口袋”的人一样。

如果是B),因为这是他们的错,他们不能羞于你不得不改变父母,因为否则你没有“好”的选择。

如果是C),您要么提交限制,要么在您的情况下,您被迫更改父级,尽管不支持。当然,这会引起皱眉,并伴随着它的警告,因为你违背了设计。

这比我预期的要长,我完成了一个你没有添加的解决方案。

鉴于您无法“删除”继承的成员,可能比更改父级更好的方法实际上是为您的特殊情况添加新的父级。如果需要删除控件,则在父级的新副本中进行更改并让子级从新的父类继承。通过这样做,您实际上是在扩展框架而不是更改框架。也许这会减少皱眉?