Reputation: 415
I am having trouble with abstract classes at the moment.
I am told I need to: "Make an abstract class called "Sprite", which stores an (x,y) position, and a reference to an Image. The constructor of your Sprite class should take 2 int parameters (to specify the initial x and y position), and a string which is the name of the file to load the image from, and it should load the image (instead of the Turtle class loading the image). It will need a getter function for the image. Make an abstract method in your Sprite class named "public void update(Graphics g)". This function should have no body. The purpose of this is to ensure that any class which inherits from this class implements an update function."
I think I understand how to make an abstract class, as I have done. I also think I did okay on the parameters in the constructor of the Sprite class. However, I've never loaded images in Java and I'm not sure how to extend/implement the abstract class functions. Is what I have done correct? And how exactly do I call that abstract class from the Turtle constructor so that the variables get set correctly? Modified, still having trouble :
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";
}
Updated 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;
}
}
Here are some samples of the code:
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.");
}
}
Upvotes: 2
Views: 5315
Reputation: 17419
You're quite well underway. The constructor for Sprite looks about right. Going over your questions:
However, I've never loaded images in Java and I'm not sure how to extend/implement the abstract class functions.
The ImageIO.read
call does the image loading for you. The sprite constructor is fine.
And how exactly do I call that abstract class from the Turtle constructor so that the variables get set correctly?
Within the constructor of a child class, you can call super( ... )
to invoke a constructor from your parent class (superclass).
Example:
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() { }
}
To call any other method of the super class, you can just type its name like normal. The super- and subclass method lists get "merged" so to speak. Think of it like putting two blueprints on top of each other and holding them in front of a light. The "Lemon" class in my example has two methods: someMethod1()
and someMethod2()
. If I created an "Apple" class without adding any methods of its own, it would only have someMethod1()
.
You've run into Cannot reference Sprite.x before supertype constructor has been called
. This is a special restriction when calling a super-constructor method. It has to do with the sequence of steps while the constructor is running.
You'll remember that an object is an instance of a class. A class is like a blueprint of what stuff the object contains. Classes have a parent class, and when an object is created, it contains the stuff of its class and all its parent classes layered on top of each other.
This layering is important during object construction, because the constructor first drills all the way down these layers (parents) and then comes back up. It's easier to explain this with an example, so here's what happens* when one of the Lemon objects from my earlier answer is constructed:
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.
*): this list leaves out some of the other stuff that happens during object creation, but it covers the bits I need for my answer.
The error occurs while you're at step 2 of this sequence. Your code is trying to access this.x
, which is not accessible until step 8.
This means you need to get the values someplace else. You have a few options:
static
variables/constants or returned by static
methods.In the case of your problem code, you can't use 2. because your Turtle constructor has no parameters. The easiest option is going to be option 1: just put the values you need between the super(
and )
.
Upvotes: 1