何时进行子类而不是区分行为

时间:2009-08-27 01:18:34

标签: c# oop

我很难决定何时应该进行子类化,而不是只添加一个代表该类不同模式的实例变量,然后让该类的方法根据所选模式进行操作。

例如,假设我有一个基本车类。在我的计划中,我会处理三种不同类型的汽车。 赛车总线家庭模型。每个人都有自己的齿轮实现,如何转动和座椅设置。我应该将我的汽车子类化为三种不同的型号,还是应该创建一个型号变量并使齿轮,车削和座椅通用,以便它们根据所选择的车型而有所不同?

在我目前的情况下,我正在开发一款游戏,而且我已经意识到它开始变得有些混乱,所以我会询问有关可能重构我当前代码的建议。基本上有不同的地图,每个地图可以是三种模式之一。根据地图定义的模式,将会有不同的行为,地图将以不同的方式构建。在一种模式中,我可能必须在超时基础上向玩家和产生生物的租金,其中另一个玩家负责产生生物,而在另一个模式中可能有一些自动生成的生物与玩家产生的生物和建造建筑物的玩家。所以我想知道是否最好有一个基本地图类,然后将其子类化为每个不同的模式,或者是否继续沿着当前添加差异化行为的路径,具体取决于地图类型变量设置为

5 个答案:

答案 0 :(得分:7)

答案 1 :(得分:3)

如果您的子类型是父类型的某种特化,您应该子类化。换句话说,如果您只需要功能,则应该避免继承。由于Liskov Substitution Principle状态:“如果S是T的子类型,则程序中类型T的对象可以用类型S的对象替换而不改变该程序的任何所需属性”

答案 2 :(得分:1)

在您谈到地图和产生的特定问题时,我认为这是您希望支持composition over inheritance的情况。当你想到它时,它们并不完全是三种不同类型的地图。相反,它们是相同的地图,有三种不同的产卵策略。因此,如果可能,您应该将产卵函数设置为单独的类,并将产卵类的实例作为地图的成员。如果地图“模式”中的所有其他差异在本质上是相似的,那么您可能根本不必对地图进行子类化,尽管为不同的组件创建子类(即具有spawn_strategy基类并从中继承三种类型的生成)或者至少给它们一个共同的界面,可能是必要的。

鉴于你的评论认为每种类型的地图在概念上都是不同的,那么我建议进行子类化,因为这似乎符合Liskov的替代原则。但是,这并不是说你应该完全放弃作曲。对于每种类型的映射具有但可能具有不同行为/实现的那些属性,您应该考虑使您的基类将它们作为组件。这样,如果需要,您仍然可以混合和匹配功能,同时使用继承来保持关注点的分离。

答案 3 :(得分:1)

在你的情况下,我将使用混合方法(这可能被称为组合,我不知道),其中您的地图模式变量实际上是一个单独的对象,它将所有相关的数据/行为存储到地图的模式。通过这种方式,您可以拥有任意数量的模式,而不会对Map类实际执行太多操作。

gutofb7将它钉在头上,以确定何时要进行子类化。给出一个更具体的例子:在你的汽车课上,你的程序中的任何地方都有什么类型的汽车吗?现在如果您将Map子类化,那么您需要编写多少代码才能处理特定的子类?

答案 4 :(得分:1)

我不用C#编程,但在Ruby on Rails,Xcode和Mootools(javascript OOP框架)中可能会问同样的问题。

我不喜欢有一种方法,当某个永久性的属性是错误的时,它永远不会被使用。就像它是一个VW Bug一样,某些齿轮永远不会转动。那太傻了。

如果我找到一些这样的方法,我会尝试抽象出所有可以在我所有不同的“汽车”中共享到父类中的东西,每种汽车都使用方法和属性,然后定义子具有特定方法的课程。