从基类继承MANY类是不好的OOP实践?

时间:2014-03-31 19:08:51

标签: oop inheritance subclass

我对这个网站比较新,所以如果我在发布问题时做错了什么,请告诉我,以便下次我能解决。

我很好奇是否从单个基类继承多个类是不好的OOP实践。这可能没有多大意义,所以我要详细说明一下。

例如,假设您正在设计游戏,并且您可能会遇到几种不同的怪物。我将采用的方法是为一般怪物对象提供一个基本抽象类,然后使用一个新类从基类中继承所有特定类型的怪物。

我的一位导师告诉我,在这种情况下你不应该依赖继承,因为怪物的数量会继续增长和增长,课程数量会增加到难以跟踪的程度所有这些都是如此,因此你将不得不重新编译程序,以及将来添加的每个新类。

我不明白为什么(或者甚至是)这是一件坏事。如果有人能帮助我理解我的教授来自哪里,那将非常感激。

谢谢!

3 个答案:

答案 0 :(得分:4)

如果怪物非常相似,那么唯一的区别是(例如)他们的名字,他们赋予了多少伤害,他们是什么颜色等等,那么这些差异可以反映在一个领域< / em>(在值中),可能不需要进行子类化。

但是,如果您拥有与其他怪物根本不同的怪物,那么必须拥有非常不同的方法和逻辑,更具体地说,无法反映的差异字段,然后可能需要子类SpecialMonster

但是,即使SpecialMonster也可能不需要被单个怪物类型细分,因为 字段可能足够区分它们。

虽然拥有特定怪物类型的百万个子类是合法的,但是当它可以简单地在新的{{{}字段中表达时,您不希望处理所有重复的代码。 1}}实例,例如

Monster

还有一种方法,你有很多课程,但你不能将它们强加给你的用户,你不会弄乱你的API / JavaDoc跟他们。如果你的怪物恰好是一个抽象类

new Monster("Goob", WakeTime.NOCTURNAL, 35, new Weapon[]{sword, hammer, knittingNeedle});
new Monster("Mister Mxyzptlk", WakeTime.ANYTIME, 71, new Weapon[]{sword, mindMeld, cardboardCutter});

然后你可以拥有像这样的Monster便利创造者:

public abstract class Monster  {
   private final String name;
   ...
   public Monster(String name, int default_damage, WakeTime wake_time, Weapon[] weapons)  {
      this.name = name;
      ...
   }
   public String getName()  {
      return  name;
   }
   ...
   public abstract int getDamage(int hit_strength);
}

为了使这些私有(实际上受包受保护的)类不显示在JavaDoc中,您需要将其access设置为/** <P>Convenience functions for creating new monsters of a specific type.</P> **/ public class NewMonsterOfType { private NewMonsterOfType() { throw new IllegalStateException("Do not instantiate."); } /** <P>Creates a new monster that is nocturnal, has 35-default-damage, and whose weapens are: sword, hammer, knittingNeedle.</P> **/ public static final GOOB = new GoobMonster(); /** <P>Creates a new monster that can be awake at any time, has 71-default-damage, and whose weapens are: sword, mindMeld, cardboardCutter.</P> **/ public static final MISTER_MXYZPTLK = new MisterMxyzptlkMonster(); } class GoobMonster extends Monster { public GoobMonster() { super("Goob", WakeTime.NOCTURNAL, 35, new Weapon[]{sword, hammer, knittingNeedle}); } public int getDamage(int hit_strength) { return (hit_strength < 70) ? getDefaultDamage() : (getDefaultDamage() * 2); } } class MisterMxyzptlkMonster extends Monster { public GoobMonster() { super("Mister Mxyzptlk", WakeTime.ANYTIME, 71, new Weapon[]{sword, mindMeld, cardboardCutter}); } public int getDamage(int hit_strength) { return (hit_strength < 160) ? getDefaultDamage() + 10 : (getDefaultDamage() * 3); } } protected

答案 1 :(得分:1)

在你的场景中继承很自然,因为所有特定的怪物都是基础怪物:)。我实际上在这里实际使用了继承,因为可能特定的怪物确实具有必须被覆盖的特定行为。 MonsterA可能会通过爬行移动,而MonsterB可能会通过飞行移动。基础AMonster将有一个抽象的 Move()方法,由这些子类型实现。

这不是最终答案,它在很大程度上取决于游戏需求,但是,在简化形式中,继承在这里是有意义的。怪物类型的数量可能会继续增长,但实际上,它们都是一样的吗?怪物设计只是基于将一些预定义的数据/行为组合在一起?这场比赛非常简单......

我真的得到了这样的印象:你的教练不会为了生活而编写游戏(我也没有,尽管我前段时间做过游戏),但他解释你为什么不能使用继承的原因也是如此。简化。定义的类的数量在应用程序中永远不是问题,单一责任原则得到尊重的越多越好。

关于你必须重新编译你的应用程序....是的,当你修复一个bug你必须重新编译它。 IMO,他给你的理由对这种情况不起作用。他需要提出更好的论据。

与此同时,继续进行继承。

答案 2 :(得分:0)

理论问题需要理论答案:)。

这不仅是坏事,而且毫无意义。你应该有一个有限数量的&#34; base&#34;从其他类继承的类,这些类应该由其他类组成(vide有利于组合与继承)。

因此,随着复杂性的增加,基类组成的类的数量应该增长。不是基类本身的数量。

就像在业内一样。例如,如果您看到机器,它们实际上是由大量的小零件组成的,其中一些小零件在不同的机器中是相同的。当您设计新机器时,您不需要订购新的独特&#34; base&#34;它的一部分就是为你的新机器命名。只有当你找不到现有的零件时,才能使用市场上现有的零件并设计一些新零件(而不是#34; base&#34;)