Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/367.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java:可能错误的抽象类实现_Java_Abstract Class - Fatal编程技术网

Java:可能错误的抽象类实现

Java:可能错误的抽象类实现,java,abstract-class,Java,Abstract Class,我之所以选择这个标题,是因为我注意到我在植入抽象类时犯了一些错误,但我还不太清楚到底是什么 为了训练目的,我创建了可移动的抽象类,并从中创建了Ball类。此外,我还仅为moveAble类创建了一个GetPosition()方法,并从ball类使用它。 但是当我对任何ball对象调用GetPosition()时,我得到的是可移动抽象对象的位置变量 我猜它应该是这样的,但是根据我的理解,我们无论如何不能使用抽象类,所以我需要能够得到子类的位置值,即使我只在父类上实现了这个方法 注意:我是一名java

我之所以选择这个标题,是因为我注意到我在植入抽象类时犯了一些错误,但我还不太清楚到底是什么

为了训练目的,我创建了可移动的抽象类,并从中创建了Ball类。此外,我还仅为moveAble类创建了一个GetPosition()方法,并从ball类使用它。 但是当我对任何ball对象调用GetPosition()时,我得到的是可移动抽象对象的位置变量

我猜它应该是这样的,但是根据我的理解,我们无论如何不能使用抽象类,所以我需要能够得到子类的位置值,即使我只在父类上实现了这个方法

注意:我是一名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];

    }
公共类Ball扩展可移动{
私有int[]位置=新int[2];
私有int[]速度={1,1};
公共球(内x_位置,内y_位置){
位置[0]=x_位置;
位置[1]=y_位置;
}
@凌驾
公共空白移动(整数宽度、整数高度){
如果(位置[0]>宽度-30 | |位置[0]<1){
速度[0]*=-1;
}
如果(位置[1]>高度-30 | |位置[1]<1){
速度[1]*=-1;
}
位置[0]+=速度[0];
位置[1]+=速度[1];
}
问题在于,您(重新)定义了类
Ball
中不同的
位置
速度
字段,该字段在Ball和子类中覆盖了从类
可移动
继承的同名字段

从类
Ball
中删除
posiion
velocity
字段。在基类
MoveAble
中,将字段的访问权限更改为
protected
,或者提供受保护的方法以允许子类访问该数据。

您可以使用抽象类型的引用。(你只是不能实例化一个抽象类。)当你调用它们的方法时,运行时的行为就是它们指向的底层具体对象的行为

抽象类可以在已知的方法中提供默认行为。我猜您的抽象类提供的行为是您的
Ball
子类完全可以接受的

这就是多态性的含义。面向对象编程有四个重要特征:抽象数据类型、封装、多态性和继承。请确保您完全理解它们


我认为您的错误是将抽象类和具体类都赋予了相同的成员变量。其中的重用在哪里?将它们从
Ball
中删除,并使它们在父类中受到保护。不要重写child中的方法,除非它们提供了不同的行为。

在提供的代码中,字段
位置
velocity
Ball
内的
可移动的
的elocity
。在您的案例中,不需要隐藏字段。如果我们从
Ball
中删除
位置
速度
,我们将得到预期的结果

至于为什么程序会这样做的原因:即使我们将字段隐藏在
Ball
中,方法
public int[]getPosition()
源于
MoveAble
,而在
MoveAble
中,
MoveAble
的字段(及其超类中的字段)是可见的


最后一点注意:
MoveAble
比抽象类更能满足接口的条件。

您可以创建一个名为IMovable的接口,以便在您只关心movable时,可以通过其接口引用此对象

现在,如果您有跨多个子类型的通用代码,您可以创建一个抽象类并在move中调用其基类代码,正如我在下面所做的,然后在子类型中添加特定于子类型的move逻辑…请参见下面的内容

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

为什么要从抽象的可移动类继承字段“position”和“velocity”,然后将它们隐藏在Ball类中?需要重写方法getPosition。属性不能重写为中的父类java@edmarisov这是不正确的。字段和方法都是继承的。(当然,私人字段是不可访问的)在Java中,除非您将其标记为受保护,否则儿童无法访问它们。否则,您只能通过getter/setter访问它们。@Andy Thomas-我将通过明确的假设来修正它:在Java中,儿童无法访问父级中的私有成员,除非您将其标记为公共或受保护。在典型情况下,父级和子级在同一个包中,包可见变量也是如此。为了封装和可维护性,我不喜欢使用受保护的字段。我创建另一个位置变量的唯一原因是使用构造函数,我不知道我可以调用超级构造函数。我真的不确定为什么以及如何在新的应用程序上使用接口类,但现在我可以看到,我可以将大部分代码放在抽象类中,并对每个可移动对象使用超级方法调用它。正如我在示例中提到的,如果您只想处理不可移动的对象,那么可以通过其单接口方法“move”引用您的类。如果您有多个接口,它将简化您的类与使用它们的客户端类的交互(客户端只使用它们感兴趣的接口)。如果您曾经使用过Swing,您知道找到某些“扩展”方法是多么令人头痛,但找到“接口”方法是多么简单“如果您感兴趣,我可以为您创建一个示例,并向您展示
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");
  }
}