我没有很多Java经验,但我看到代码中有一个带有某个构造函数的抽象类,然后是没有构造函数的抽象类的子类。然后,当实例化子类时,它使用其超类构造函数构造。是吗?
我有这个抽象类:
public abstract class Tile{
public int x;
public int y;
public int z;
protected Color color;
protected float friction;
protected float bounce;
protected boolean liquid;
public void Tile(int x, int y, int z){
this.x = x;
this.y = y;
this.z = z;
init();
}
abstract protected void init();
这个子类:
public class TestTile extends Tile{
protected void init(){
color = Color.RED;
friction = 0.1f;
bounce = 0.2f;
liquid = false;
}
}
但是当我用这个实例化TestTile时:
Tile tile = new TestTile(0, 0, 0);
init()方法永远不会运行。其中定义的所有值都为null。我尝试制作我可能是子类中的冗余构造函数,它只是用完全相同的参数调用super,但是当我这样做时,即使使用super(x,y,z)内部唯一的语句,它也说:
TestTile.java:27:调用super必须是构造函数中的第一个语句
我想制作一堆Tile的子类来实现Tile的属性。如果这不是正确的方法,那么更好的方法是什么?
如果它与任何东西有关,我使用的是32位Ubuntu Linux 11.04。
感谢。
答案 0 :(得分:6)
您的构造函数不是属性构造函数格式,它是void
,使它成为:
public Tile(int x, int y, int z){
this.x = x;
this.y = y;
this.z = z;
init();
}
答案 1 :(得分:1)
我没有看到TestTime的构造函数带有三个参数。我根本没有看到任何ctor,这意味着你所拥有的只是编译器给你的默认值。我走得太快而想念它吗?
我建议你注意这点。我重新考虑这个设计:
What's wrong with overridable method calls in constructors?
试试这个 - 它包含了构造函数的修复,并避免了另一个线程指出的问题:
public abstract class Tile{
public int x;
public int y;
public int z;
protected Color color;
protected float friction;
protected float bounce;
protected boolean liquid;
public Tile(int x, int y, int z){
this.x = x;
this.y = y;
this.z = z;
}
}
public class TestTile extends Tile{
// You're missing this.
public TestTile(int x, int y, int z)
{
super(x, y, z);
this.init();
}
protected void init(){
color = Color.RED;
friction = 0.1f;
bounce = 0.2f;
liquid = false;
}
}
答案 2 :(得分:1)
首先,Tile
只有一个带x,y,z参数的构造函数,没有默认构造函数,所以你必须在TestTile
构造函数中调用super(x,y,z) 。正如slandau所述,“构造函数”具有错误的void
返回类型。
TestTile
需要声明参数或传递默认值:
public TestTile(int x, int y, int z) {
super(x, y, z);
}
public TestTile() {
super(0, 0, 0);
}
在Java中,有很多riscs可以在构造函数中调用抽象方法,另请参见here,实例未正确初始化。你只能安全地调用静态方法(这在这里不起作用)。
public TestTile(int x, int y, int z) {
super(x, y, z);
color = Color.RED;
friction = 0.1f;
bounce = 0.2f;
liquid = false;
}
或者您需要在派生类中调用私有方法(从init()
中删除抽象Tile
):
public TestTile(int x, int y, int z) {
super(x, y, z);
init();
}
private void init() {
color = Color.RED;
friction = 0.1f;
bounce = 0.2f;
liquid = false;
}
您确定会员在这里是正确的实施吗?也许抽象方法(getter)在这里声明一个行为并在子类中实现它可能更好吗?
public abstract class Tile {
public int x;
public int y;
public int z;
public Tile(int x, int y, int z) {
this.x = x;
this.y = y;
this.z = z;
}
public abstract Color getColor();
public abstract float getFriction();
public abstract float getBounce();
public abstract boolean isLiquid();
}
public class TestTile extends Tile {
public TestTile(int x, int y, int z) {
super(x, y, z);
}
public Color getColor() {
return Color.RED;
}
public float getFriction() {
return 0.1f;
}
public float getBounce() {
return 0.2f;
}
public boolean isLiquid() {
return false;
}
}
答案 3 :(得分:0)
构造函数不是继承的,因此在创建TestTile对象时不会调用Tile的三参数构造函数。您需要从TestTile构造函数中显式调用三参数Tile构造函数,就像您说的那样,但是对super(x,x,x)的调用必须是TestTile构造函数的第一个语句。
就像Matt Ball所说的那样,在删除void返回类型之前,你的Tile“构造函数”并不是真正的构造函数。