2010-05-13 112 views
5

对于我的学期项目,我和我的团队应该创建一个包含游戏开发框架并演示OOP概念的.jar文件(库,不可运行)。它应该是一个框架,另一个团队应该使用我们的框架,反之亦然。所以我想知道我们该如何开始。我们考虑了几种方法:
1.从一个普通类抽象基类或类?

public class Enemy { 
    public Enemy(int x, int y, int health, int attack, ...) { 
     ... 
    } 
    ... 
} 
public class UserDefinedClass extends Enemy { 
    ... 
} 

2.开始用一个抽象类,用户定义的敌人要继承抽象成员

public abstract class Enemy { 
    public Enemy(int x, int y, int health, int attack, ...) { 
     ... 
    } 
    public abstract void draw(); 
    public abstract void destroy(); 
    ... 
} 
public class UserDefinedClass extends Enemy { 
    ... 
    public void draw() { 
     ... 
    } 
    public void destroy() { 
     ... 
    } 
} 

3.创建全部继承的超级ABC(抽象基类)

public abstract class VectorEntity { 
    ... 
} 
public abstract class Enemy extends VectorEntity { 
    ... 
} 
public class Player extends VectorEntity { 
    ... 
} 
public class UserDefinedClass extends Enemy { 
    ... 
} 

我应该使用哪一个?或者,还有更好的方法?

回答

6

那么,如果不深入地了解自己在做什么,那么有点难以确定,即使如此,它也是相当主观的。但是,有些事情需要考虑哪些可以告诉你。

  1. 他们是要真正实例化一个敌人,还是所有的敌人真的需要是派生类型?如果你实际上不会实例化敌人而不是衍生类型,那么它应该可能是一个接口或一个抽象类。

  2. 如果您希望在您的基类中提供实际行为,那么显然它需要是类而不是接口。

  3. 需要在API中存在的方法,但对您提供任何实现没有任何意义应该是抽象的。

  4. 在基类中为它们实现它们是很有意义的方法应该在基类中有实现。如果它们没有意义的被覆盖,那么就让它们成为最终的。

  5. 让类共享一个共同的基类真的只有在他们真的共享行为时才有意义,或者你需要能够在代码中的某处处理它们。如果他们不是那么相似,那么他们可能不应该共享一个基类。例如,如果Enemy和Player都应该是可显示的,则拥有处理其显示功能的公共基类是有意义的。但是如果敌人是可以显示的东西,并且玩家是一个更抽象的概念 - 就像游戏的控制者 - 并且不可显示,那么他们共享基类可能就没有意义了。一般来说,在构建类时,最好选择组合而不是继承,所以如果所讨论的类不是真的要共享行为,并且与公共基类没有真正的“is-a”关系,那么他们不应该共享一个共同的基类。

  6. 宁愿让您的基类只共享方法,而不是数据。换句话说,在继承树中,最好只有叶子是可实例化的。有很多东西,例如equals(),当你有基类,其中有实际的数据时会崩溃。这并不是说你不能这么做 - 人们总是这样做 - 但它可能会导致问题,如果不需要,最好避免。

  7. 倾向于重写抽象方法。否则,在派生类中,您可能无法调用基类的方法或完全改变方法的功能。

我敢肯定,我可以想出更多,但是如果没有真正熟悉您的项目,它肯定是相当通用的。在你给出的3个选项中,我可能会使用2. 3似乎你可能会为不相关的类创建一个基类,并且1会导致Enemy被实例化,这可能不需要肯定会使它比你的继承层次中的叶子更能实例化。您可能仍然会以基类中的数据为2,但您更可能只是重写抽象方法,并且在派生类中更改行为的问题较少。

0

我的行为准则是​​,只要有多个共享相同操作/数据/方法/功能的类,它们就应该是同一个抽象类的扩展。

所以,如果是我做这件事:

  • 如果所有的类都具有一个共同点,即都在一个地方收集这一功能/场/数据的顶级abstract class
  • 如果他们不这样做,只有那些实际上有共同点的类应该扩展一个较低层次的abstract class

如果只有方法是类将具有的共同点,那么也可以使用interface。但是,我总是发现,迟早我会看到实现interface的类具有相同的private字段。此时,我将interface转换为包含这些私有字段的abstract class(如果没有其他内容,则保存在代码行中)。

1

第四种选择是使用接口。

interface Enemy { 

    public void draw(); 

    . . . 

} 

如果你刚开始,我会避免你的第三个选项。让框架发展一点,看看是否需要它。

0

只是一个小的回答出的书“更有效的C++”页271:

“让基类的抽象是不是在一个层次结构的结尾”。我懒得给你整个chapert,但作者列出了一些很好的理由。

+0

还有“有效的Java”,在这种情况下更适用。它描述了类似的东西,但是对于Java更特定的东西 - 比如当基类不全是抽象类型时,如果equals()并不适用于混合派生类型和基类型。 – 2010-05-14 18:44:25