Java如何实现和设计抽象类

Java如何实现和设计抽象类,java,abstract,protected,Java,Abstract,Protected,我在java代码中遇到了一个设计问题。我的应用程序使用的是飞弹,有不同类型的飞弹,它们的工作原理完全相同,只是它们有3个独特的属性。导弹的制造者必须知道这些属性。我决定让飞弹成为一个抽象类,但我不能在方法/构造函数之外的子类中为受保护的变量赋值。而且我不能在构造函数中声明变量,因为我必须首先调用超级构造函数。 在这个问题上我怎么能聪明点 public abstract class Missile { private int x, y; private Image image; boolean

我在java代码中遇到了一个设计问题。我的应用程序使用的是飞弹,有不同类型的飞弹,它们的工作原理完全相同,只是它们有3个独特的属性。导弹的制造者必须知道这些属性。我决定让飞弹成为一个抽象类,但我不能在方法/构造函数之外的子类中为受保护的变量赋值。而且我不能在构造函数中声明变量,因为我必须首先调用超级构造函数。 在这个问题上我怎么能聪明点

public abstract class Missile {

private int x, y;
private Image image;
boolean visible;

private final int BOARD_WIDTH = 390;

protected final int MISSILE_SPEED;
protected final int MISSILE_HEIGHT;
protected String file;

public Missile(int x, int y) {
    ImageIcon ii =
        new ImageIcon(this.getClass().getResource(file));
    image = ii.getImage();
    visible = true;
    this.x = x;
    this.y = y - Math.floor(MISSILE_HEIGHT/2);
}


public Image getImage() {
    return image;
}

public int getX() {
    return x;
}

public int getY() {
    return y;
}

public boolean isVisible() {
    return visible;
}

public void move() {
    x += MISSILE_SPEED;
    if (x > BOARD_WIDTH)
        visible = false;
}
}
还有一个理想的子类实现,除了它不工作。(它无法识别受保护的变量)。我该怎么办

public class Laser extends Missile {

    MISSILE_SPEED = 2;
    MISSILE_HEIGHT = 5;
    file = "laser.jpg";

public Laser(int x, int y) {
    super(x, y);
}

}

我认为最好的方法是在Missile中创建子类必须实现的抽象方法。例如,将这些添加到导弹:

public abstract int getMissileSpeed();
public abstract int getMissileHeight();
public abstract int getFileName();
然后您的子类必须实现它,您可以将其设置为常量,如下所示:

public class Laser extends Missile {

    public Laser(int x, int y) {
        super(x, y);
    }

    public int getMissileSpeed() {
        return 2;
    }

    public int getMissileHeight() {
        return 5;
    }

    public String getFileName() {
        return "laser.jpg";
    }

}

编辑:当然,只要调用这些方法,就可以在任何要检索常量值的地方进行编辑。

将基类字段和构造函数更改为

protected final int speed;
protected final int height;

public Missile(int x, int y, int speed, int height, String file) {
    ImageIcon ii =
        new ImageIcon(this.getClass().getResource(file));
    image = ii.getImage();
    visible = true;
    this.speed = speed;
    this.height = height;
    this.x = x;
    this.y = y - Math.floor(height/2);
}
和子类,以:

public class Laser extends Missile {
    public Laser(int x, int y) {
        super(x, y, 2, 5, "laser.jpg");
    }

    ...
}

这些属性已经在基类中,因此不能在子类中重新定义它们。在Java中,所有大写的命名都保留给常量。

我不确定飞弹是否需要是一个抽象类,但我认为这样的东西可能就是你想要的:

public abstract class Missile {

    private int x, y;
    private Image image;
    boolean visible;

    private final int BOARD_WIDTH = 390;

    protected final int MISSILE_SPEED;
    protected final int MISSILE_HEIGHT;

    public Missile(int x, int y, int speed, int height, String file) {
        MISSILE_SPEED = speed;
        MISSILE_HEIGHT = height;

        ImageIcon ii = new ImageIcon(this.getClass().getResource(file));
        image = ii.getImage();
        visible = true;
        this.x = x;
        this.y = y - Math.floor(MISSILE_HEIGHT/2);
    }

}

public class Laser extends Missile {

    public Laser(int x, int y) {
        super(x, y, 2, 5, "laser.jpg");
    }

}

创建一个接口并将所有最终字段放入其中。
现在在导弹和激光中实现这个接口。至少这可以解决访问问题。

@trevor-e不,编译器仍然会请求它们的标识符。为什么不将导弹类的构造函数参数化,以同时接受导弹速度/导弹高度。这些可以从子类传递,但不需要从子类公开constructors@DevBlanked由于我只有两个不同的导弹,这将消除对导弹抽象的需要。我只是觉得给导弹4 int参数不是一个很好的解决方案。我一直在寻找一种方法来避免这种情况。如果OP不打算在imo上添加更多字段,这是一个很好的快速解决方案。否则构造函数参数的数量会增加很多,您需要重构到生成器模式来管理它。是的,或者将多个字段包装到一个对象中(如x和y的点。但这比从基类的构造函数调用可重写的方法要好得多,就像接受的答案一样。这是一种糟糕的做法,因为基类构造函数调用该方法时,子类字段还不会初始化。是的,我正在试验这种想法。我希望会这样别这么说。有什么理由你没有文件属性的抽象方法吗?(因为不同的导弹有不同的动画)@user2651804抱歉忘了添加它!我实际上喜欢这个解决方案,因为您可以轻松地根据需要扩展任意多的属性。要做到这一点,您只需添加到基础抽象类,然后您的IDE就可以帮助您轻松地将它们添加到所有子类中。这可能是一个我可能非常喜欢的解决方案。这不是一个非常详细的答案-ca你能详细说明这是怎么回事吗?