以父函数参数作为函数参数的纯java调用方法

8nuwlpux  于 2021-07-03  发布在  Java
关注(0)|答案(4)|浏览(462)

在我的项目中我遇到了这个问题,我有一个抽象的实体类,它的子类是player,shot和敌人。我要检查他们之间有没有碰撞。一个单独的物理类正在使用以下代码进行碰撞评估:

public class Physics {

    private static int height = 32;
    private static int width = 32;

    public static void collision(Entity entity, LinkedList<Entity> eList) {
        for (int i = 0; i<eList.size(); i++) {
            if (entity.getBounds(width, height).intersects(eList.get(i).getBounds(width, height))) {
               entity.collidesWith(eList.get(i));
             }
         }
     }
}

linkedlist包含快照和敌人,但是由于某些原因,碰撞只调用collideswith(实体)方法,而不是collideswith(快照b)或collideswith(敌人e)。
edit:提到的类(在本例中,只有我认为对它们很重要的代码)
实体:

public abstract class Entity {

protected double x;
protected double y;

public Entity (double x, double y) {
    this.x = x;
    this.y = y;
}

public abstract void tick();

public double getX() { return x; }
public double getY() { return y; }

public Rectangle getBounds(int width, int height) {
    return new Rectangle((int)x, (int)y, width, height);
}

public abstract void collidesWith(Entity e);
public abstract void collidesWith(Enemy e);
public abstract void collidesWith(Shot s);

玩家:

public class Player extends Entity {

private boolean alive;

private int gameWidth, gameHeight;
private GameController gCont;
private Textures textures;

public Player( String name, int x, int y, int gameWidth, int gameHeight, Textures textures, GameController gCont) {
    super(x,y);
    this.name = name;
    this.score = 0;
    this.gameWidth = gameWidth;
    this.gameHeight = gameHeight;
    this.gCont = gCont;
    this.textures = textures;
    this.alive = true;
}

public void tick() {        
    gCont.collisionCheck(this);
}

public void collidesWith(Enemy e) {
    System.out.println("Player collides with enemy");
    this.alive = false;
}
public void collidesWith(Shot s) {
    return;
}

public void collidesWith(Entity e) {
    System.out.println("collided with entity");
    return;
}

射击

public class Shot extends Entity {

private Textures textures;
private GameController gCont;

public Shot(double x, double y, Textures textures, GameController gCont) {
    super(x, y);
    this.textures = textures;
    this.gCont = gCont;
}

public void tick() {
    x+=10;
    gCont.collisionCheck(this);

}

public void collidesWith(Entity e) {
    return;
}

public void collidesWith(Enemy e) {
    gCont.removeEntity(e);
    gCont.removeEntity(this);
    gCont.addScore();
}

@Override
public void collidesWith(Shot s) {
    return;     
}

敌人

public class Enemy extends Entity {
private int speed;

public Enemy(double x, double y) {
    super(x, y);
    Random random = new Random();       
    speed = random.nextInt(3)+1;
}

public void tick() {
    x-=speed;
}

public void collidesWith(Entity e) {
    return;
}

@Override
public void collidesWith(Enemy e) {
    return;

}

@Override
public void collidesWith(Shot s) {
    return;     
}

如何让它调用正确的函数?

cbjzeqam

cbjzeqam1#

我认为除了jamie bisotti指定的泛型类型之外,还有一个解决方案,就是使用接口和开关来检查哪个类是what。
这是一个接口,它声明了所有可能发生冲突的实体必须具有的方法:

public interface Collidable {
    public boolean collidesWith(Collidable entity);
}

然后,您希望能够碰撞的每个类都必须实现:

public class Enemy extends Entity implements Collidable {
private int speed;

public Enemy(double x, double y) {
    super(x, y);
    Random random = new Random();       
    speed = random.nextInt(3)+1;
}

public void tick() {
    x-=speed;
}

@Override
public void collidesWith(Collidable e) {

    if (e.getClass().equals(Shot.class)) {
        // DO SOMETHING, I am colliding with a shot
    } else if(e.getClass().equals(Enemy.class)) {
        // I am colliding with an Enemy
    }

    . . . etc
}

我更喜欢使用接口,这样我可以指定每个行为。目前看来一切都很简单,所有的东西都可以从实体抽象类中扩展出来,但是有那么一刻,您将通过许多其他特性来区分每个实体。
例如,一个飞行的敌人,一个行走的敌人,ecc ecc,你可以用一个接口来指定每个特征。
在这种情况下,接口也非常简单。但是您可以指定许多要实现的方法,例如

public boolean canCollide();
public boolean isAlive(); //if the entity is already dead you might want not to stop a bullet
public boolean isAnimatingDeath(); //if the entity is animating death could collide with another antity because of its exploding animation, maybe you want to avoid that.

您可以在抽象实体类中实现som方法,但是抽象实体不应该知道它的子实体。这就是为什么要实现一些方法,直接在子对象中使用泛型“可合并”类型作为输入。

prdp8dxp

prdp8dxp2#

对我来说,实体类了解敌人和射击是错误的。
为什么不从实体和子类中删除这两个方法:

public abstract void collidesWith(Enemy e);
public abstract void collidesWith(Shot s);

仅保留和实施:

public abstract void collidesWith(Entity e);

如果需要知道作为参数传递的实体e的类型,可以使用反射,但这是一种糟糕的设计。最好实现collideswith,这样就不需要知道所传递参数的确切类型。

pgx2nnw8

pgx2nnw83#

查看java的泛型。我想你可以用这样的方法:

public abstract class Entity<T> {

    protected double x;
    protected double y;

    public Entity (double x, double y) {
        this.x = x;
        this.y = y;
    }

    public abstract void tick();

    public double getX() { return x; }
    public double getY() { return y; }

    public Rectangle getBounds(int width, int height) {
        return new Rectangle((int)x, (int)y, width, height);
    }

    public abstract void collidesWith(T e);
}
xtfmy6hx

xtfmy6hx4#

可能是错的,我对回答stackoverflow的问题还不熟悉。
希望这能让你明白: entity.collidesWith(eList.get(i)); get(i)在那一行中,在物理类entity中返回一个entity类型的对象。这是因为它的定义如下: LinkedList<Entity> eList 这意味着,如果有一个重载接受该实体,它只会调用该方法。这正是我在你的代码里看到的。您有一个参数为:entity的“collideswith”的方法重载。在实体的所有子类中。
我认为您应该多读一些关于“java多态性”的内容。

相关问题