Java类继承

Java类继承,java,inheritance,class,Java,Inheritance,Class,,它说: 这给了MountainBike所有与Bicycle相同的字段和方法,但允许其代码专门关注使其独特的功能。这使得子类的代码易于阅读。但是,您必须注意正确地记录每个超类定义的状态和行为,因为这些代码不会出现在每个子类的源文件中 然而,在我的代码中,继承不能正常工作,可能是因为我的代码中存在缺陷 package java1; class bicycle { int speed = 0; int gear = 1; void accelerate(int incr)

,它说:

这给了MountainBike所有与Bicycle相同的字段和方法,但允许其代码专门关注使其独特的功能。这使得子类的代码易于阅读。但是,您必须注意正确地记录每个超类定义的状态和行为,因为这些代码不会出现在每个子类的源文件中

然而,在我的代码中,继承不能正常工作,可能是因为我的代码中存在缺陷

package java1;

class bicycle {
    int speed = 0;
    int gear = 1;

    void accelerate(int incr) {
        speed = speed + incr;
    }

    void decelerate(int incr) {
        speed = speed - incr;
    }

    void changeGear(int val) {
        gear = val;
    }

    void printInfo() {
        System.out.println("Speed: " + speed + " Gear: " + gear);
    }
}

class mountainbike extends bicycle {
    int speed = 10;
}

public class Main {

    public static void main(String[] args) {

        mountainbike mb1 = new mountainbike();

        mb1.accelerate(20);
        mb1.accelerate(10);

        mb1.printInfo();

    }

}
mountainbike类应该继承自行车类的所有特性,对吗?我添加了一个独特的属性,它是
int speed=10
,所以启动速度应该是10。但是,在运行编译器时,将启动速度视为0


有什么想法吗?

没有,你的
山地车
课程不应该重新定义
速度
变量。您需要使用
super
作为构造函数调用的一部分,将初始速度(
10
)传递给其超类的构造函数:

package java1;

class Bicycle
{

  Bicycle(int speed, int gear)
  {
    this.speed = speed;
    this.gear = gear;
  }

  public void accelerate(int incr)
  {
    speed = speed + incr;
  }

  public void decelerate(int incr)
  {
    speed = speed - incr;
  }

  void changeGear(int val)
  {
    gear = val;
  }

  public String toString()
  {
    return "Speed: " + speed + " Gear: " + gear;
  }

  private int speed = 0;
  private int gear = 1;

}

class Mountainbike extends Bicycle
{
  public Mountainbike()
  {
    super(10, 1);
  }
}

public class Main {

  public static void main(String[] args)
  {    
    Mountainbike mb1 = new Mountainbike();

    mb1.accelerate(20);
    mb1.accelerate(10);

    System.out.println(mb1);
  }
}

我建议不要对速度和档位使用
受保护的
变量。通过在基类中声明
speed
gear
变量
private
来强制封装是一种很好的做法


编辑:


显然,您是从Java编程开始的。我建议你看看布鲁斯·埃克尔(Bruce Eckel)写的这本免费在线书。

事实上,你正在重新定义你班上的山地车的场地速度

class mountainbike extends bicycle {
 mountainbike() {
   speed=10;
 }
}
例如,您可以在mountainbike类的构造函数中初始化速度

class mountainbike extends bicycle {
 mountainbike() {
   speed=10;
 }
}
您在
mountainbike
中引入了一个新的
速度
变量,它隐藏了
自行车
中的一个变量。这是一个坏主意-在类型层次结构的不同级别使用两个同名变量会导致混淆,尤其是当它们都可以访问时

相反,您希望将现有变量的值更改为10。例如:

class mountainbike extends bicycle {
    mountainbike() {
        speed = 10;
    }
}

在我看来,字段在基类中应该是私有的,而不是通过属性访问的——正如其他人所说,在基类中使用接受初始速度的构造函数也是一个好主意。

您不能重写字段,只能重写方法。您需要做的是将
speed
字段标记为
protected
,向子类添加构造函数并在该构造函数中设置字段的值,如下所示:

public class Bicycle {
   private int speed;

   public Bicycle (int speed) {
      this.speed = speed;
   }
}


public class Mountainbike extends Bicycle {
   public Mountainbike() {
      super(10);
   }
}
class Mountainbike extends Bicycle {
    public Mountainbike()
    {
        speed = 10;
    }
}

顺便说一句,请注意,我已经更正了您的类名:Java对大写类名有着极其强大的约定;使用小写类名只会让查看代码的人感到困惑。

在Java中,有一个概念是。发生的情况是速度变量实际上没有被覆盖,因此它仍然默认为0

您正在使用
mountainbike.speed
隐藏自行车.speed
,因此基本上每个mountainbike实例都有两个速度的int成员变量,一个是
this.speed
,另一个是
this.super.speed


不要在mountainbike中重新定义int speed,你只需要为mountainbike创建一个默认构造函数,并设置
this.speed=xxx在那里。

不能重写字段,只能重写方法

class bicycle {
    int getSpeed() {
        return 0;
    }
    // ... other things
}

class mountainbike extends bicycle {
    int getSpeed() {
        return 10;
    }
    // ... other things
}

下面的投票人能指出问题所在吗?我建议不要使用
protected
变量。
private int speed
变量可以更好地强制封装。如何将其标记为受保护?我知道如何在构造函数中设置字段(这意味着变量,对吗?)的值,但我不知道如何保护字段。@Fabian:您只需编写
protectedint-speed声明变量时。请参见仅在字段名前面写上“受保护”(字段是非局部变量)。这意味着子类中的代码可以直接访问该字段,即使它们不在同一个包中——因此,您的代码可能不需要该字段,稍后可能会在课程中介绍该字段。但是Gregory是对的-r3zn1k的解决方案更干净。或者我的:p无论如何,欢迎来到Java,我们希望你喜欢飞行第二辆
公共自行车(int-speed){
(第4行)对于?@Fabian Sun的解决方案:对于访问修饰符的解释,只有两页之遥:感谢您的回复。显然,在编程世界中有多种方法可以绕过障碍:D现在我想我将使用构造函数并分配
speed=10
,为了简单起见,我真的不知道如何使用t他是
public
private
以及
super()
之类的人。