最好扩展一个类或直接修改它?

时间:2010-04-28 16:21:11

标签: java class extend

所以我正在为Java中的数据结构创建可视化。我已经开始实现数据结构(二进制搜索树),但我需要为包含的节点类添加一些额外的功能。就约定和最佳实践而言,我是否应该使用此附加功能创建节点的子类,还是应该修改我拥有的内容并将其记录在那里?

我的问题类似于问here,但这有点过头了。

我知道这对我正在做的事情并不重要,所以我更多地要求这一点。

编辑:我可能应该更清楚。我的修改实际上并没有改变原始实现,只是添加了几个额外的字段(x和y coords以及一个布尔值来设置是否突出显示该节点)以及访问/修改这些字段的函数。我正在使用的节点类也包含在BST实现中

从阅读你的答案看起来似乎有两个案例的争论。我同意创建一个单独的类或接口可能是最好的事情。创建另一个类似乎可能会变得棘手,因为您仍然需要一种从节点中提取数据的方法。我正在使用的BST实现是通用的,并且在Node类或BST类中没有任何这样的功能只返回数据,所以至少我必须添加它。

感谢您提供丰富的回复。

5 个答案:

答案 0 :(得分:11)

要回答的问题是,当您没有可视化数据结构时,“基本功能”是否有用,甚至是不可取的?

您甚至可能根本不想扩展课程。没有更多细节,在我看来,你有一个有效的数据结构。您可以创建一个知道如何对其进行虚拟化的新类。

也就是说,代替数据结构而不是知道如何可视化自身,您有一个数据结构,另一个知道如何可视化数据结构的类。哎呀 - 您可能会发现它会演变成另一个完整的类层次结构,因为您可能需要可视化队列,堆栈等等。无需使用二进制搜索树。

答案 1 :(得分:3)

既然你一般都在问,这里的答案很简短:这实际上取决于具体情况

首先,假定子类与其父类具有“IS-A”关系。如果你不能说你的新子类是一个特定类型的原始类,你就会问错误的问题,并且应该创建一个新的,无关的类。

  • 如果新代码与类的核心目的密切相关,并且适用于类的所有成员(例如所有BST),则修改可能更好。高cohesion很好。
  • 如果您的新代码与该类的核心目的相关,但仅与该类型的某些对象有关(例如,只有平衡的BST),则子类化可能是要走的路
  • 根据您正在更改的内容,代码的使用位置,使用它的人/组织的数量,以及您的更改可能会导致其他代码中的意外行为,因此您应该三思而后行在修改现有代码之前。这并不意味着自动对常用事物进行子类化;由于上述原因,这通常是错误的。

在您的具体情况下,我同意n8wrl;由于可视化与数据结构无关,因此实现一个完整的单独Visualizable接口可能比创建DrawableBSTNode子类更好。

答案 2 :(得分:2)

我想说在向现有实现添加功能的一般情况下,您应该扩展现有的实现而不是修改它。

这是我的推理。如果除了二进制搜索树实现之外的任何地方使用该节点,那么当您修改它时,您需要找到它用于确保这些位置都不与您的修改冲突的任何地方。虽然只是以新方法的形式添加功能通常不会导致问题,但可能会导致问题。你永远不知道如何使用一个物体。

其次,即使它仅用于二进制搜索树,您仍然需要确保BST的实现与您的修改一致。

最后,如果你扩展它,你不必担心第一点和第二点。并且您可以获得额外的好处,即您的修改始终与原始实施分开。这样可以更轻松地跟踪您所做的事情并对其进行评论。

答案 3 :(得分:2)

没有简单的答案,知道何时以及如何添加功能是你必须要学习的东西。

只是添加到基类似乎是一个简单的解决方案,但它污染了您的基类。如果这是一个类,你可以合理地期望使用另一个程序(甚至你的程序的一部分),你所添加的功能是否适合你班级的责任?如果不是这可能是一个不好的举动。您是否添加了将基类链接到特定用途的依赖项?因为如果你正在抛出代码重用窗口。

继承是许多工程师所倾向的解决方案,这是一条诱人的路线。但是,随着我成长为工程师,这是我谨慎使用的。继承只应用于真正的is-a关系,并且需要来尊重behavioral subtyping 或者你以后会后悔的。而且由于Java只允许单继承,这意味着你只能在子类型中获得一次。

组合(尤其是界面)通常是一个更好的主意。通常看起来像是一种关系的关系实际上是一种关系。或者有时您真正需要的是一个辅助类,它有许多函数可以将原始类作为参数。

然而,有了一个问题,想要将这些对象存储在树中。这里的解决方案是接口。您不需要存储节点的树。您希望对象具有可以为您提供节点的接口。

public interface HasNode {
    public Node getNode();
}

你的节点类是一个带有getNode的HasNode,只是返回它。您的NodeVisualizer类也是一个HasNode,现在您也可以在树中存储NodeVisualizers。当然现在你有另一个问题,你的树可能包含NodeVisualizers和Nodes,这不会很好。另外,当您从树函数中获取HasNode时,您必须将它们转换为正确的实例,这很难看。你会想要使用模板,但这是另一个答案。

答案 4 :(得分:0)

混合逻辑上独立的功能会导致混乱。子类化是一种非常特殊的关系,经常被过度使用。子类化用于Is-a-Kind关系。

如果你想要想象一下,为什么不为它创建一个完全独立的类呢?您可以简单地将Node对象传递给它。 (或者甚至更好,使用接口。)