【问题标题】:Extending an Abstract Class扩展抽象类
【发布时间】:2014-09-27 10:36:04
【问题描述】:

目前我遇到了抽象类的问题。

有人告诉我我需要: “创建一个名为“Sprite”的抽象类,它存储(x,y)位置和对图像的引用。Sprite 类的构造函数应采用 2 个 int 参数(指定初始 x 和 y 位置),以及一个字符串,它是要从中加载图像的文件的名称,它应该加载图像(而不是加载图像的 Turtle 类)。它将需要一个 getter 函数来获取图像。在其中创建一个抽象方法你的 Sprite 类名为“public void update(Graphics g)”。这个函数应该没有主体。这样做的目的是确保从这个类继承的任何类都实现更新函数。"

我想我知道如何创建一个抽象类,就像我所做的那样。我也认为我在 Sprite 类的构造函数中的参数做得很好。但是,我从来没有在 Java 中加载过图像,我不确定如何扩展/实现抽象类函数。我所做的是否正确?以及如何从 Turtle 构造函数中调用该抽象类,以便正确设置变量? 修改了,还是有问题:

    class Turtle extends Sprite
{
    private int x;
    private int y;
    private static int dest_x;
    private static int dest_y;
    private String image;

   // private Sprite sprite;


 Turtle() {
           // super();
            super(x, y, image);
            image = "turtle.png";

          }

更新的 Sprite 类

import java.awt.Graphics;
import javax.imageio.ImageIO;
import java.awt.Image;
import java.io.File;
import java.io.IOException;

public abstract class Sprite
{

int x;
int y;
String imageName;

Image image;

Sprite(){}

public Sprite(int x1, int y1, String im)
{

//Store variables


    imageName = im;
    x1 = x;
    y1 = y;

    try {
        image = ImageIO.read(new File(imageName));

    } catch (IOException ioe) {
        System.out.println("Unable to load image file.");

    }
}


public abstract void update(Graphics g);

public Image getImage()
{

    return image;

}



}

以下是一些代码示例:

import java.awt.Graphics;
import java.awt.Image;
import javax.imageio.ImageIO;
import java.io.File;
import java.io.IOException;

class Turtle extends Sprite
{
    private int x;
    private int y;
    private static int dest_x;
    private static int dest_y;
    private String image;

   // private Sprite sprite;


 Turtle() {

            image = "turtle.png";

          }

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

    public void setX(int xIn) { x = xIn; }
    public void setY(int yIn) { y = yIn; }

    public void update(Graphics g) {
        // Move the turtle
        if (x < dest_x) {
            x += 1;
        } else if (x > dest_x) {
            x -= 1;
        }

        if (y < dest_y) {
            y += 1;
        } else if (y > dest_y) {
            y -= 1;
        }

        // Draw the turtle


        g.drawImage(image, x, y, 100, 100, null);



    }

import java.awt.Graphics;
import javax.imageio.ImageIO;
import java.awt.Image;
import java.io.File;
import java.io.IOException;

public abstract class Sprite
{

int X;
int Y;
String image;

Image Image;

Sprite(){}

public Sprite(int x, int y, String im)
{

//Store variables


    image = im;
    X = x;
    Y = y;

    try {
        Image = ImageIO.read(new File(image));

    } catch (IOException ioe) {
        System.out.println("Unable to load image file.");

    }
}

【问题讨论】:

  • 抽象的 Sprite 类通常看起来不错(考虑将变量从 Image 命名为 image,因为 Java 约定。您也不需要存储 String 图像),但是,image 的 getter 方法丢失了。在您的Turtle 类中,您使用super 语句调用超类构造函数,在您的情况下为super(x, y, image)。由于这些变量(xyimage)是在您的抽象类中定义的,因此您的子类中不需要它们。
  • 谢谢!但我仍然感到困惑,因为它不允许我以这种方式调用超级构造函数。我将我的代码修改为这个,它告诉我:“在显式调用构造函数时不能引用实例字段 x”它正在为所有参数执行此操作。 :/ 我的更新代码在旧代码之上。

标签: java constructor abstract-class


【解决方案1】:

你进展顺利。 Sprite 的构造函数看起来很正确。复习你的问题:

但是,我从来没有在 Java 中加载过图像,而且我不确定如何扩展/实现抽象类函数。

ImageIO.read 调用会为您加载图像。精灵构造函数很好。

以及如何从 Turtle 构造函数中调用该抽象类以正确设置变量?

在子类的构造函数中,您可以调用super( ... ) 来调用父类(超类)的构造函数。

例子:

public abstract class Fruit {
    public Fruit(String name) {
       //stuff...
    }

    public void someMethod1() { }
}

public class Lemon extends Fruit {
    public Lemon() {
        // child class constructor calling superclass constructor
        super("John");

        // child class constructor calling own method:
        someMethod2();

        // child class constructor calling superclass method:
        someMethod1();
    }

    public void someMethod2() { }
}

要调用超类的任何其他方法,您可以像往常一样输入它的名称。可以说,超类和子类方法列表“合并”了。把它想象成把两个蓝图放在一起,然后把它们放在灯前。我的示例中的“Lemon”类有两种方法:someMethod1()someMethod2()。如果我创建了一个“Apple”类而不添加它自己的任何方法,它只会有someMethod1()

后续问题更新:

您遇到了Cannot reference Sprite.x before supertype constructor has been called。这是调用超级构造方法时的特殊限制。它与构造函数运行时的步骤顺序有关。

你会记得一个对象是一个类的一个实例。类就像对象包含的内容的蓝图。类有一个父类,当一个对象被创建时,它包含了它的类和它所有的父类的东西,它们相互叠加。

这种分层在对象构造过程中很重要,因为构造函数首先会一直向下钻取这些层(父层),然后再向上钻取。用一个例子更容易解释这一点,所以当我之前的答案中的一个 Lemon 对象被构造时,会发生以下情况*

1. Lemon constructor call
   2. Fruit constructor call (super-constructor of Lemon)
      3. java.lang.Object constructor call (super-constructor of Fruit)
      4. java.lang.Object constructor body
      5. Everything at the java.lang.Object inheritance level now ready to use.
   6. Fruit constructor body
   7. Everything at the Fruit inheritance level now ready to use.
8. Lemon constructor body
9. Everything at the Lemon inheritance level now ready to use.

*):这个列表忽略了在对象创建过程中发生的一些其他事情,但它涵盖了我需要回答的部分。

当您处于此序列的第 2 步时,会发生错误。您的代码正在尝试访问 this.x,直到第 8 步才能访问。

这意味着您需要在其他地方获取值。您有几个选择:

  1. 只需在此处将值作为文字输入即可。
  2. 使用您自己的参数列表中的值。
  3. 使用定义为static 变量/常量或由static 方法返回的值。

对于您的问题代码,您不能使用 2. 因为您的 Turtle 构造函数没有参数。最简单的选项是选项 1:只需将您需要的值放在 super() 之间即可。

【讨论】:

  • 谢谢!但是我仍然很困惑,因为它不允许我以这种方式调用超级构造函数。我将我的代码修改为这个,它告诉我:“在显式调用构造函数时不能引用实例字段 x”它正在为所有参数执行此操作。 :/ 我的更新代码在旧代码之上。
猜你喜欢
  • 2016-11-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-12
相关资源
最近更新 更多