Расширение абстрактного класса

У меня сейчас проблемы с абстрактными классами.

Мне сказали, что мне нужно: "Создать абстрактный класс под названием"Sprite", который хранит позицию (x,y) и ссылку на изображение. Конструктор вашего класса Sprite должен принимать 2 параметра типа int (чтобы указать начальный x и y position), а также строка, которая является именем файла, из которого загружается изображение, и она должна загружать изображение (вместо класса Turtle, загружающего изображение). Для изображения потребуется функция получения. абстрактный метод в вашем классе 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.");

    }
}

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( а также ),

Другие вопросы по тегам