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