Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java: possible wrong abstract class impletaion

I chose this title because I noticed that I did something wrong with the implantation of abstract class but I'm not quite sure what yet.

I created the MoveAble abstract class for training purposes and created the Ball class from it. Also I created a GetPosition() method only for the moveAble class and use it from the ball class. But when I called GetPosition() on any ball object, i got the position varibale of the Moveable Abstract object instead.

I'm guessing its suppose to be that way, but from my understanding we can't use abstract class anyway, so I need to be able to get the position value of the child class even if I implemented this method only on the parents class.

Note: I'm a beginner java programmer. there is probably a better way to do what I did, but that's what I came out with. I would like to hear what you guys think about it, A if you think it's all crooked and there is a better way for all of this I will be glad to learn it.

Moveable class:

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) ;

The ball class:

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];

    }
like image 577
Smiled_One Avatar asked Feb 09 '23 13:02

Smiled_One


2 Answers

In the code provided, the fields position and velocity of MoveAble within Ball were hidden. As rodit pointed out, there is no need to hide the fields in your case. If we remove the fields position and velocity from Ball, we get the expected result.

As to the reason why the program does what it does: even if we hide the fields within Ball, the method public int[] getPosition() stems from MoveAble and within MoveAble, the fields of MoveAble (and those from its superclass) are visible.

One last note: MoveAble satisfies more the conditions of an interface than an abstract class. Here is a discussion about when to use interfaces vs. when to use abstract classes

like image 176
Turing85 Avatar answered Feb 12 '23 06:02

Turing85


You can create an interface called IMovable so that you may refer to this object through its interface when you only care about movables...

Now, if you have common code across several subtypes, you can create an Abstract class and invoke its base class code in move, as I have done below, and then add subtype specific move logic in the subtype ... see below

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);
}

Another benefit of referring to an instance via its interface is that eclipse auto-complete feature will limit it's list of items to the interface methods alone.

enter image description here

Compare that to the explosion of methods that are displayed in auto-complete when you refer to the same object but through its inheritance hierarchy.

enter image description here

Which one makes more sense?

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");
  }
}
like image 29
Constantin Avatar answered Feb 12 '23 06:02

Constantin