Java:可能错误的抽象类实现
我之所以选择这个标题,是因为我注意到我在植入抽象类时犯了一些错误,但我还不太清楚到底是什么 为了训练目的,我创建了可移动的抽象类,并从中创建了Ball类。此外,我还仅为moveAble类创建了一个GetPosition()方法,并从ball类使用它。 但是当我对任何ball对象调用GetPosition()时,我得到的是可移动抽象对象的位置变量 我猜它应该是这样的,但是根据我的理解,我们无论如何不能使用抽象类,所以我需要能够得到子类的位置值,即使我只在父类上实现了这个方法 注意:我是一名java程序员初学者。也许有更好的方法来做我所做的事情,但这就是我的想法。我想听听你们怎么想,A如果你们认为这一切都是错误的,并且有更好的方法来解决这一切,我会很高兴地学习它 可移动类别:Java:可能错误的抽象类实现,java,abstract-class,Java,Abstract Class,我之所以选择这个标题,是因为我注意到我在植入抽象类时犯了一些错误,但我还不太清楚到底是什么 为了训练目的,我创建了可移动的抽象类,并从中创建了Ball类。此外,我还仅为moveAble类创建了一个GetPosition()方法,并从ball类使用它。 但是当我对任何ball对象调用GetPosition()时,我得到的是可移动抽象对象的位置变量 我猜它应该是这样的,但是根据我的理解,我们无论如何不能使用抽象类,所以我需要能够得到子类的位置值,即使我只在父类上实现了这个方法 注意:我是一名java
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");
}
}