繁体   English   中英

抽象基类还是类?

[英]Abstract Base Class or Class?

对于我的学期项目,我的团队和我应该创建一个包含游戏开发框架并展示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.创建ALL继承的超级ABC(抽象基类)

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

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

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

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

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

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

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

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

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

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

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

第四种选择是使用接口。

interface Enemy {

    public void draw();

    . . .

}

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

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

所以,如果是我这样做:

  • 如果所有类都有共同点,请使用顶级abstract class ,在一个位置收集此功能/字段/数据。
  • 如果他们不这样做,只有那些实际上有共同点的类应该扩展一个低级abstract class

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

只是“更有效的c ++”第271页中的一个小答案:

“使基类不抽象,而不是在层次结尾”。 我懒得给你整个教练,但是autor列出了一些很好的理由。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM