我目前在抽象课上遇到麻烦。
我被告知我需要: "创建一个名为" Sprite"的抽象类,它存储(x,y)位置和对Image的引用。 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 Class
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.");
}
}
答案 0 :(得分:0)
你正在进行中。 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之前无法访问。
这意味着您需要在其他地方获取值。您有几个选择:
static
变量/常量或由static
方法返回的值。对于您的问题代码,您不能使用2.因为您的Turtle构造函数没有参数。最简单的选项是选项1 :只需将您需要的值放在super(
和)
之间。