抽象基类还是类?

Moh*_*nde 5 java abstract-class class

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

public class Enemy {
    public Enemy(int x, int y, int health, int attack, ...) {
        ...
    }
    ...
}
public class UserDefinedClass extends Enemy {
    ...
}
Run Code Online (Sandbox Code Playgroud)

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() {
        ...
    }
}
Run Code Online (Sandbox Code Playgroud)

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

public abstract class VectorEntity {
    ...
}
public abstract class Enemy extends VectorEntity {
    ...
}
public class Player extends VectorEntity {
    ...
}
public class UserDefinedClass extends Enemy {
    ...
}
Run Code Online (Sandbox Code Playgroud)

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

Jon*_*vis 6

嗯,如果不深入了解你正在做什么,有点难以肯定,即便如此,这也是相当主观的.但是,有些事情需要考虑,可以告诉你.

  1. 他们是否会真正实例化敌人,或者所有敌人真的需要属于派生类型吗?如果你实际上并不是要实例化Enemies而不是派生类型,那么它应该是一个接口或一个抽象类.

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

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

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

  5. 让类共享一个共同的基类真的只有在他们真正分享行为或者你需要能够在代码中的某个地方处理它们时才有意义.如果他们真的不那么相似,那么他们可能不应该共享一个基类.例如,如果Enemy和Player都应该是可显示的,那么拥有一个处理其显示功能的公共基类可能是有意义的.但是如果Enemy是可以显示的东西,并且Player是一个更抽象的概念 - 比如游戏的控制器 - 并且不可显示,那么它们分享基类可能没有意义.一般来说,在构建类时最好更喜欢组合而不是继承,所以如果有问题的类实际上不是共享行为而且实际上与公共基类没有"is-a"关系,那么他们不应该共享一个共同的基类.

  6. 希望您的基类只共享方法,而不是数据.换句话说,在继承树中,最好只有叶子是可实例化的.equals()当你的基类中包含实际数据时,会有各种各样的错误.这并不是说你不能这样做 - 人们总是这样做 - 但它可能会导致问题,如果不需要,最好避免.

  7. 更喜欢覆盖抽象方法.否则,在派生类中,您可能无法调用基类的方法或完全改变方法的作用.

我确信我可以提出更多,但如果没有真正熟悉你的项目,它必然是相当通用的.在你提供的3个选项中,我可能会选择2. 3看起来你可能正在为不相关的类创建一个基类,而1会导致Enemy被实例化,你可能不需要和肯定会使你的继承层次结构中的叶子不仅可以实例化.您可能仍然会在基类中使用2结束数据,但您更有可能只重写抽象方法,并且在派生类中更改行为的问题会更少.