对于我的学期项目,我的团队和我应该创建一个包含游戏开发框架并展示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 {
...
}
我应该使用哪个?或者有更好的方法吗?
答案 0 :(得分:6)
嗯,如果不深入了解你正在做什么,有点难以肯定,即便如此,这也是相当主观的。但是,有些事情需要考虑,可以告诉你。
他们是否真的要实例化敌人,或者所有敌人真的需要属于派生类型吗?如果你实际上不是要实例化Enemies而不是派生类型,那么它应该是一个接口或一个抽象类。
如果您希望在基类中提供实际行为,那么显然它需要是一个类而不是一个接口。
需要为API提供但对您提供任何实现没有任何意义的方法应该是抽象的。
在基类中实现它们很有意义的方法应该在基类中有实现。如果对他们进行覆盖没有多大意义,那就让他们做最后的决定。
让类共享一个公共基类真的只有在他们真正分享行为或者你需要能够在代码中的某个地方处理它们时才有意义。如果他们真的不那么相似,那么他们可能不应该共享一个基类。例如,如果Enemy和Player都应该是可显示的,那么拥有一个处理其显示功能的公共基类可能是有意义的。但是如果Enemy是可以显示的东西,并且Player是一个更抽象的概念 - 比如游戏的控制器 - 并且不可显示,那么它们分享基类可能没有意义。一般来说,在构建类时最好更喜欢组合而不是继承,所以如果有问题的类实际上不是共享行为而且实际上与公共基类没有“is-a”关系,那么他们不应该共享一个共同的基类。
希望您的基类只共享方法,而不是数据。换句话说,在继承树中,最好只有叶子是可实例化的。有许多类似equals()
的东西,如果你的基类中包含实际数据,它们会分解。这并不是说你不能这样做 - 人们总是这样做 - 但它可能会导致问题,如果不需要,最好避免。
首选覆盖抽象方法。否则,在派生类中,您可能无法调用基类的方法或完全改变方法的作用。
我确信我能提出更多,但如果没有真正熟悉你的项目,它必然是相当通用的。在你提供的3个选项中,我可能会选择2. 3看起来你可能正在为不相关的类创建一个基类,而1会导致Enemy被实例化,你可能不需要和肯定会使你的继承层次结构中的叶子不仅可以实例化。您可能仍然会在基类中使用2结束数据,但是您更有可能只重写抽象方法,并且在派生类中更改行为的问题会更少。
答案 1 :(得分:1)
第四种选择是使用接口。
interface Enemy {
public void draw();
. . .
}
如果你刚刚开始,我会避免你的第三种选择。让框架发展一点,看看是否需要它。
答案 2 :(得分:0)
我的行为准则是,只要有多个类共享相同的操作/数据/方法/功能,它们就应该是同一个抽象类的扩展。
所以,如果是我这样做的话:
abstract class
在一个位置收集此功能/字段/数据。 abstract class
。如果只有方法是这些类的共同点,那么也可以使用interface
。但是,我总是发现,我迟早会看到实现interface
的类具有相同的private
字段。此时,我将interface
转换为保存这些私有字段的abstract class
(如果没有其他内容则保存在代码行上)。
答案 3 :(得分:0)
第271页“更有效的c ++”一书中的一个小答案:
“使基类抽象不在层次结尾”。我懒得给你整个专栏,但是autor列出了一些很好的理由。