为什么要继承
为了提高代码的复用性,当多个类存在相同的属性和方法时,可以从这些类中抽象出父类,在父类中定义这些相同的属性和方法名,子类只需要通过extends来声明父类即可。
继承的基本语法
class 子类 extends 父类{
}
- 子类会自动拥有父类的方法与属性
- 父类叫超类,基类
- 子类叫派生类
举例
建立猫科动物类,并且定义相关属性
package com.zss.ClassLearn;
public class Feild {
public String name;
public int age;
public int speed;
public void yell(){
System.out.println("我是动物"+name+"今年"+age+"岁了,我奔跑的速度为"+speed);
}
}
建立老虎类继承猫科动物
package com.zss.ClassLearn;
public class Tiger extends Feild{
public static void main(String[] args) {
Tiger tiger=new Tiger();
tiger.name="老虎阿华";
tiger.age=2;
tiger.speed=200;
tiger.yell();
}
}
建立狮子类继承猫科动物
package com.zss.ClassLearn;
public class Lion extends Feild{
public static void main(String[] args) {
Lion lion=new Lion();
lion.name="狮子阿美";
lion.age=3;
lion.speed=1999;
lion.yell();
}
}
继承的好处
- 代码复用性提高
- 代码的扩展性与维护性提高
继承的细节问题
- 子类虽然继承了父类的方法和属性,但是私有属性不能在子类中直接访问,需要通过父类提供的公共封装方法去访问。
子类在使用过程中必须调用父类的构造器,才能给父类赋值,大家查看以下的一段代码以及运行结果
package com.zss.ClassLearn;
public class Feild {
public String name;
public int age;
public int speed;
public void yell(){
System.out.println("我是动物"+name+"今年"+age+"岁了,我奔跑的速度为"+speed);
}
public Feild(){
System.out.println("我是父类的无参构造器,如果子类运行时这句话出现,表示我被调用了");
}
}
package com.zss.ClassLearn;
public class Tiger extends Feild{
public static void main(String[] args) {
Tiger tiger=new Tiger();
tiger.name="老虎阿华";
tiger.age=2;
tiger.speed=200;
tiger.yell();
}
public Tiger(){
System.out.println("我是子类的无参构造器");
}
}
- 当我们创建子类时,不管使用子类的哪一个构造器,默认情况下总会调用父类的无参构造器(也就是说,我们用了多少次子类构造器,就用了多少次父类构造器)。
- 如果父类没有提供无参构造器,则必须在子类的构造器中使用super指定使用父类的哪一个构造器完成对父类工作的初始化工作,否则编译不会通过(也就是说我们如果没有在父类中定义无参构造器,但是父类中存在有参数的构造器,并且子类中没有指定,会发生异常报错,这个时候就需要我们来进行指定)
我们运行一下下面一段代码来看看这些关系:
父类
package com.zss.ClassLearn;
public class Feild {
public String name;
public int age;
public int speed;
public void yell(){
System.out.println("我是动物"+name+"今年"+age+"岁了,我奔跑的速度为"+speed);
}
/*public Feild(){
System.out.println("我是父类的无参构造器,如果子类运行时这句话出现,表示我被调用了");
}*/
public Feild(String name){
System.out.println("我是父类的只有名字参数的构造器,如果子类运行时这句话出现,表示我被调用了");
}
public Feild(String name,int age,int speed){
System.out.println("我是父类的拥有全部参数的构造器,如果子类运行时这句话出现,表示我被调用了");
}
}
子类老虎
package com.zss.ClassLearn;
public class Tiger extends Feild{
public static void main(String[] args) {
Tiger tiger=new Tiger();
tiger.name="老虎阿华";
tiger.age=2;
tiger.speed=200;
tiger.yell();
}
public Tiger(){
//仅仅调用了有名字的构造器
super("花花");
System.out.println("我是子类的无参构造器");
}
}
子类狮子
package com.zss.ClassLearn;
public class Lion extends Feild{
//这里调用了拥有所有参数的构造器
public Lion() {
super("辛巴",30,2000);
}
public static void main(String[] args) {
Lion lion=new Lion();
lion.name="狮子阿美";
lion.age=3;
lion.speed=1999;
lion.yell();
}
}
- super与this都只能放在构造器发第一行,因此这两个方法不能共存在一个构造器中
- Java所有的类都是object的子类
- 父类构造器的调用不限于直接父类,将一直调用追溯到object类
- 子类最多只能继承一个父类(直接继承),在Java中时单继承机制