2015-07-15 1 views
4

Я выбрал этот заголовок, потому что заметил, что я сделал что-то не так с имплантацией абстрактного класса, но пока не совсем уверен.Java: возможно неправильный абстрактный класс impletaion

Я создал абстрактный класс MoveAble для тренировочных целей и создал из него класс Ball. Также я создал метод GetPosition() только для класса moveAble и использовал его из класса ball. Но когда я вызвал GetPosition() на любом шаровом объекте, вместо этого я получил переменную положения объекта Moveable Abstract.

Я предполагаю, что это так, но из моего понимания мы все равно не можем использовать абстрактный класс, поэтому мне нужно получить значение позиции дочернего класса, даже если бы я реализовал этот метод только по классу родителей.

Примечание: Я начинающий программист на Java. вероятно, лучший способ сделать то, что я сделал, но это то, с чем я вышел. Я хотел бы услышать, что вы, ребята, думаете об этом, A, если вы считаете, что это все криво, и есть лучший способ для всего этого, я буду рад узнать его.

Подвижный класс:

public abstract class MoveAble { 
    private int[] position = new int[2]; 
    private int[] velocity = { 1, 1 }; 

    public int[] getPosition() { 
    return position; 
    } 
    public abstract void move(int width, int height) ; 

Класс мяч:

public class Ball extends MoveAble{ 

    private int[] position = new int[2]; 
    private int[] velocity = { 1, 1 }; 

    public Ball(int x_position, int y_position) { 

     position[0] = x_position; 
     position[1] = y_position; 
    } 

    @Override 
    public void move(int width, int height) { 
     if (position[0] > width - 30 || position[0] < 1) { 
      velocity[0] *= -1; 
     } 
     if (position[1] > height - 30 || position[1] < 1) { 
      velocity[1] *= -1; 
     } 
     position[0] += velocity[0]; 
     position[1] += velocity[1]; 

    } 
+0

Почему вы хотите наследовать поля «позиция» и «скорость» из абстрактного класса MoveAble, а затем затенять их в классе Ball? – rodit

+0

Вам необходимо переопределить метод getPosition. Свойства не переопределяются родительскому классу в java – edmarisov

+1

@edmarisov Это неверно. Филды наследуются, как и методы. (частные поля, конечно, недоступны) – dsh

ответ

1

Вы можете создать интерфейс IMovable, так что вы можете обратиться к этому объекту через интерфейс, когда вы заботитесь только о движимости ...

Теперь, если у вас есть общий код через несколько подтипов, вы можете создать абстрактный класс и вызвать его базового класса код в движении, как я сделал ниже, а затем добавить подтип специфическую логику перемещения в подтипе ... смотри ниже

public class Ball extends AbstractBall { 
    public Ball(int x_position, int y_position) { 
     super(x_position, y_position); 
    } 

    public void move(int width, int height) { 
     super.move(width, height); 
     System.out.println("SUBTYPE-CLASS MOVE IS CALLED"); 
    }   

     public static void main(String[] args) { 
       Ball ball = new Ball(10, 20); 
       ball.move(1, 2); 
     } 
} 

abstract class AbstractBall implements IMovable { 

    protected int[] position = new int[2]; 
    protected int[] velocity = { 1, 1 }; 

    public AbstractBall(int x_position, int y_position) { 
     position[0] = x_position; 
     position[1] = y_position; 
    } 

    public void move(int width, int height) { 

     System.out.println("BASE-CLASS MOVE IS CALLED"); 

     if (position[0] > width - 30 || position[0] < 1) { 
      velocity[0] *= -1; 
     } 
     if (position[1] > height - 30 || position[1] < 1) { 
      velocity[1] *= -1; 
     } 
     position[0] += velocity[0]; 
     position[1] += velocity[1]; 
    }   
} 

interface IMovable { 
    public void move(int width, int height); 
} 

еще одно преимущество со ссылкой на экземпляр через интерфейс заключается в том, что функция автозаполнения eclipse будет ограничивать список элементов методами интерфейса a одинокий.

enter image description here

Сравните это взрыв методов, которые отображаются в автозаполнения, когда вы ссылаетесь на тот же объект, но через иерархии наследования.

enter image description here

Какой имеет смысл?

import javax.swing.JButton; 

public class Demo { 

    public static void main(String[] args) { 

    IPrintable instance1 = new PrintableButton(); 
    instance1.print(); 

    PrintableButton instance2 = new PrintableButton(); 
    instance2.print(); 
    } 
} 

interface IPrintable { 
    public void print(); 
} 

class PrintableButton extends JButton implements IPrintable { 
    private static final long serialVersionUID = 1L; 

    @Override 
    public void print() { 
    System.out.println("Printable Button"); 
    } 
} 
+0

Единственная причина, по которой я сделал другую переменную позиции, - использовать конструктор, которого я не знал, вместо этого я могу назвать супер-конструктор. Я действительно не знаю, почему и как и использовать интерфейсы еще в новых классах, но теперь я вижу, что могу поместить большую часть своего кода в абстрактный класс и называть его супер-методом для каждого перемещаемого объекта. –

+1

Как я уже упоминал в моем примере, если все, что вы хотите сделать, это иметь дело с объектами IMoveable, вы можете обратиться к своему классу с помощью метода одностороннего интерфейса «переместить».Если у вас несколько интерфейсов, это упрощает взаимодействие вашего класса с используемыми ими классами клиентов (клиенты используют только тот интерфейс, который им интересен). Если вы когда-либо использовали Swing, вы знаете, какая головная боль заключается в том, чтобы найти определенные «расширенные «методы, но как просто найти методы« интерфейса ».« Если вам интересно, я могу создать для вас пример и показать вам, что я имею в виду. Дайте мне знать – Constantin

+0

Да @Constantin, это было бы замечательно –

1

Проблема заключается в том, что вы (повторно) определены различные position и velocity поле в классе Ball, что внутри Болл и подклассов , затмевает поля с таким же именем, унаследованные от класса MoveAble.

Извлеките поля posiition и velocity из класса Ball. Измените доступ полей к protected в базовом классе MoveAble или, альтернативно, предоставите защищенные методы, чтобы позволить подклассам доступ к этим данным.

+1

Для инкапсуляции и ремонтопригодности предпочитайте * не * использовать защищенные поля. –

1

ссылки, которые являются абстрактными типами. (Вы просто не можете создать экземпляр абстрактного класса.) Когда вы вызываете их методы, поведение во время выполнения - это базовый конкретный объект, на который они указывают.

Абстрактный класс может обеспечивать поведение по умолчанию в методах, если он известен. Я предполагаю, что ваш абстрактный класс обеспечивает поведение, которое вполне приемлемо для вашего дочернего класса Ball.

Вот что такое полиморфизм. Объектно-ориентированное программирование имеет четыре важные характеристики: абстрактные типы данных, инкапсуляция, полиморфизм и наследование. Убедитесь, что вы их полностью понимаете.

Я думаю, что ваша ошибка дает как абстрактные, так и конкретные классы одинаковым переменным-членам. Где это повторное использование? Удалите их с Ball и сделайте их защищенными в родительском. Не переопределяйте методы в дочернем, если они не обеспечивают различное поведение.

5

Вы hid the fieldsposition и velocity от MoveAble в пределах Ball. Как rodit pointed out, нет необходимости скрывать поля в вашем случае. Удалите поля position и velocity от Ball, и вам должно быть хорошо идти.

Что касается причины почему программа делает то, что он делает: даже если вы спрятали поля в Ball, метод public int[] getPosition() проистекает из MoveAble и в MoveAble, поля MoveAble (и только те, в том числе поля, унаследованные от родительские классы).

Последнее примечание: MoveAble удовлетворяет условиям интерфейса, чем абстрактный класс. Here is an discussion about when to use interfaces vs. when to use abstract classes

Смежные вопросы