簡體   English   中英

Java:當我實例化抽象 Class 的子類時,它無法識別其超類的構造函數

[英]Java: When I Instantiate a Subclass of an Abstract Class It Doesn't Recognize the Constructor of its Superclass

我沒有太多的 Java 經驗,但我看到代碼中存在抽象 class 和某個構造函數,然后是該抽象 class 的子類而沒有構造函數。 然后當子類被實例化時,它會用它的超類構造函數來構造。 那正確嗎?

我有這個抽象的 class:

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。

謝謝。

您的構造函數不是屬性構造函數格式,它是void ,使它:

public Tile(int x, int y, int z){
        this.x = x;
        this.y = y;
        this.z = z;
        init();
    }

我沒有看到需要三個 arguments 的 TestTime 構造函數。 我根本看不到任何 ctor,這意味着您所擁有的只是編譯器為您提供的默認值。 我是不是 go 太快而錯過了它?

我建議要特別注意這一點。 我會重新考慮這個設計:

構造函數中可覆蓋的方法調用有什么問題?

試試這個 - 它包括對您的構造函數的修復,並避免其他線程指出的問題:

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;
    }
}

首先, 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 中,在構造函數中調用抽象方法的風險很多,參見此處,實例未正確初始化。 您只能安全地調用 static 方法(此處不起作用)。

public TestTile(int x, int y, int z) {
  super(x, y, z);
  color = Color.RED;
  friction = 0.1f;
  bounce = 0.2f;
  liquid = false;
}

或者您需要在派生的 class 中調用私有方法(從Tile中刪除抽象init() ):

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;
  }

}

構造函數不是繼承的,所以在創建TestTile object時不會調用Tile的三參數構造函數。 您需要從 TestTile 構造函數中顯式調用三參數 Tile 構造函數,就像您說的那樣,但是對 super(x,x,x) 的調用必須是 TestTile 構造函數的第一條語句。

就像 Matt Ball 所說的那樣,在您刪除 void 返回類型之前,您的 Tile “構造函數”並不是真正的構造函數。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM