我目前还不确定继承最适合我的Java程序,或者最好是否使用接口实现。我正在讨论的上下文的一个例子如下。
想象一下,我正在制作游戏,我的游戏中有敌人。这些敌人都有各种各样的变量和行为,但在某种程度上都是独一无二的。例如,Enemy1,
class Enemy1 {
float x, y, width, height;
public Component(float x, float y, float width, float height) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
}
public void AI() {
//some code
}
}
和Enemy2,
class Enemy2 {
float x, y, width, height;
public Component(float x, float y, float width, float height) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
}
public void AI() {
//some different code
}
}
所以对于这两个不同的敌人,我理解(或者至少相信)我可以将Enemy2改为类似
class Enemy2 extends Enemy1 {
@Override
public void AI() {
//some different code
}
}
但是,现在如果我有五种不同类型的AI代码,每个敌人可以拥有,然后不是为每个敌人在类中定义AI行为的代码,我想要另一个包含所有敌人的类AI,允许我扩展/实现AI类/接口并选择我想要的那个。
我不确定最好的办法是做什么的。简而言之,我希望有不同的敌人共享属性,每个属性中都有类似但不同的功能(例如AI代码),但总体来说仍然是非常独特的。仅使用课程来实现这一目标是否最有效?接口?我该怎么做呢?我是否会有一个班级从班级中汲取课程?或者只是一个类扩展一个类并同时实现一个接口?我不太清楚最好的继承结构是什么用。
对不起,如果我有任何根本的误解或错误。
非常感谢任何帮助。
答案 0 :(得分:1)
类Enemy2扩展了Enemy1
这在语义上是否有意义? Enemy2
还是Enemy1
吗?对游戏一无所知,让我们说Enemy1
是一只恐狼,而Enemy2
是一只熊。熊也不是恐狼,所以这种结构毫无意义。但是,如果Enemy2
是一个Dire Wolf Pack Leader,那么这个将有意义,因为它也是一个恐怖狼。
我想要另一个包含所有AI的类
这对我来说听起来很奇怪。一个对象包含其他对象的所有逻辑,并从中提取逻辑?这听起来非常接近“上帝对象”的反模式。您应该将逻辑保留在拥有它的对象上。
根据描述,听起来你想要一个abstract class。一个基础Enemy
类,它本身不能被实例化,但它拥有所有敌人的共性。类似的东西:
abstract class Enemy {
float x, y, width, height;
public Enemy(float x, float y, float width, float height) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
}
abstract public void AI();
}
然后任何敌人都会继承:
class DireWolf extends Enemy {
public DireWolf(float x, float y, float width, float height) {
super(x, y, width, height);
}
public void AI () {
//...
}
}
实际上,任何扩展Enemy
的类都将由编译器 来实现AI()
。因此,通用功能和通用接口保存在抽象基类中,从中继承的每个类都将为该接口提供实现。
修改强>
此方法需要constructor for every child class。这可能对您有利,例如,如果每个DireWolf的大小相同,构造函数可能如下所示:
public DireWolf(float x, float y) {
super(x, y, 64, 64);
}
然后你可以按如下方式初始化你的狼:
Enemy wolf = new DireWolf(0, 0);
答案 1 :(得分:1)
您可以使用过程函数创建一个抽象的AI类:
abstract class AI
{
public abstract void process(Enemy en);
}
然后你可以扩展它。
class AISipleMovement extends AI
{
@Override
public void process(Enemy en)
{
en.moveRandomly(); //Insert actual code here
}
}
或只是:
class AIStayFrozen extends AI
{
@Override
public void process(Enemy en)
{
}
}
在敌人类中:
class Enemy1 {
float x, y, width, height;
AI ai;
public Enemy1(float x, float y, float width, float height, AI ai) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.setAI(ai)
}
public void setAI(AI aiIn)
{
this.ai = aiIn;
}
public void AI() {
ai.process(this);
}
}
当然,这是一个最小的例子,你应该覆盖ai
是否为空以防止NullPointerException和类似的东西。