Java 继承


目录
  • 一、为什么需要继承?
  • 二、继承的介绍
  • 三、继承的基本语法
  • 四、继承给编程带来的便利
  • 五、继承的细节
  • 六、继承的本质
  • 七、练习

一、为什么需要继承?

我们编写了两个类,一个是Pupil类(小学生),一个是Graduate(大学毕业生)

问题:两个类的属性和方法有很多相同,怎么办?

  • 这个时候就需要继承(代码复用性)

二、继承的介绍

继承可以解决代码复用,让我们的编程更加靠近人类思维.当多个类存在相同的属性(变量)和方法时,可以从这些类中 抽象出父类,在父类中定义这些相同的属性和方法,所有的子类不需要重新定义这些属性和方法,只需要通过 extends 来 声明继承父类即可。

示意图如下

image-20220127165530874

三、继承的基本语法

class 子类 extends 父类{
    
}
  1. 子类就会自动拥有父类定义的属性和方法
  2. 父类又叫超类,基类
  3. 子类又叫派生类

例:

Student父类

package com.hspedu.extend_.improve_;

//父类,是Pupil和Graduate的父类
public class Student {
    public String name;
    public int age;
    private double score;

    public void setScore(double score) {
        this.score = score;
    }

    public void showInfo(){
        System.out.println("学生名 " + name + " 年龄 " + age + " 成绩 " + score);
    }
}

Pupil子类

package com.hspedu.extend_.improve_;

public class Pupil extends Student {
    public void testing(){
        System.out.println("小学生  正在考小学数学..." );
    }
}

Graduate子类

package com.hspedu.extend_.improve_;

//让Graduate 继承Student的类
public class Graduate extends Student {
    public void testing() {//和pupil不一样
        System.out.println("大学生 " + name + " 正在考大学数学...");
    }
}

四、继承给编程带来的便利

  1. 代码的复用性提高了
  2. 代码的扩展性和维护性提高了

五、继承的细节

  1. 子类继承了所有的属性和方法,非私有的属性和方法可以在子类直接访问,但是私有属性和方法不能在子类直接访问,要通过父类提供公共的方法去访问

  2. 子类必须调用父类的构造器,完成父类的初始化

    public Sub(){
        //super();默认调用父类的无参构造器,
        //super()会放在子类的第一条语句
        System.out.println("子类 Sub()构造器被调用....");
    }
    
  3. 当创建子类对象时,不管使用子类的哪个构造器,默认情况下总会去调用父类的无参构造器,如果父类没有提供无参构造器,则必须在子类的构造器中用 super 去指定使用父类的哪个构造器完成对父类的初始化工作,否则,编译不会通过(怎么理解。)

  4. 如果希望指定去调用父类的某个构造器,则显式的调用一下 : super(参数列表)

  5. super在使用的时候必须放在第一行,super只能在构造器中使用

  6. super() 和 this() 都只能放在构造器第一行,因此这两个方法不能共存在一个构造器

  7. java 所有类都是 Object 类的子类, Object是所有类的超类

image-20220128105049944

  1. 父类构造器的调用不限于直接父类!将一直往上追溯直到 Object 类

  2. 子类最多只能继承一个父类(指直接继承)即 java 中是单继承机制

  3. 不能滥用继承,子类和父类之间必须满足 is-a 的逻辑关系


六、继承的本质

内存布局图

image-20220128163137556

package com.hspedu.extend_;

public class ExtendsTheory {
    public static void main(String[] args) {
        Son son = new Son(); //内存到底发生了什么
        //?-> 这时要按照查找关系来返回信息
        //1.先看看子类是否有该属性
        //2.如果子类有这个属性,并且可以访问,则返回信息
        //3.如果子类没有这个属性,就看父类有没有这个属性(如果父类有该属性,并且可以访问,就返回信息..)
        //4.如果父类没有就按照 3. 的原则,继续找上级父类,直到Object...
        System.out.println(son.name);//返回的就是大头儿子
//        System.out.println(son.age);//不行,报错,说age在father类中,且是私有的
        System.out.println(son.getAge());//返回的是39
        System.out.println(son.hobby);
    }
}

class GrandPa{//爷爷类
    String name = "大头爷爷";
    String hobby = "旅游";
    int age = 100;
}
class Father extends  GrandPa{//父类
    String name = "大头爸爸";
    private int age = 39;

    public int getAge() {
        return age;
    }
}

class Son extends Father{ //子类
    String name = "大头儿子";
}

注意:继承按照以下的查找原则来返回信息

  1. 先看看子类是否有该属性
  2. 如果子类有这个属性,并且可以访问,则返回信息
  3. 如果子类没有这个属性,就看父类有没有这个属性(如果父类有该属性,并且可以访问,就返回信息..)
  4. 如果父类没有就按照 3. 的原则,继续找上级父类,直到Object...
  5. 如果查找到的属性是私有的不能直接访问,就会报错

七、练习

题目:

  1. 编写 Computer 类,包含 CPU、内存、硬盘等属性,getDetails 方法用于返回 Computer 的详细信息

  2. 编写 PC 子类,继承 Computer 类,添加特有属性【品牌 brand】

  3. 编写 NotePad 子类,继承 Computer 类,添加特有属性【color】

  4. 编写 Test 类,在 main 方法中创建 PC 和 NotePad 对象,分别给对象中特有的属性赋值,以及从 Computer 类继承的 属性赋值,并使用方法并打印输出信息

Computer类

package com.hspedu.extend_.Exercise;

/*1.编写 Computer 类,包含 CPU、内存、硬盘等属性,
    getDetails 方法用于返回 Computer 的详细信息
 */
public class Computer {
     private String cpu ;
     private String memory ;
     private String hardDisk;

    public Computer(String cpu, String memory, String hardDisk) {
        setCpu(cpu);
        setMemory(memory);
        setHardDisk(hardDisk);
    }

    public String getCpu() {
        return cpu;
    }

    public void setCpu(String cpu) {
        this.cpu = cpu;
    }

    public String getMemory() {
        return memory;
    }

    public void setMemory(String memory) {
        this.memory = memory;
    }

    public String getHardDisk() {
        return hardDisk;
    }

    public void setHardDisk(String hardDisk) {
        this.hardDisk = hardDisk;
    }

    //用于返回Computer的详细详细
    public String getDetails(){
        return "CPU:" + cpu + "\nMemory:"+memory + "\nHardDisk:" + hardDisk;
    }
}

PC类

package com.hspedu.extend_.Exercise;

//编写 PC 子类,继承 Computer 类,
// 添加特有属性【品牌 brand】
public class PC extends Computer{
    private String brand;

    //这里IDEA 根据继承的规则,自动的把构造器的调用写好
    //这里也体现:继承设计的基本思想,父类的构造器完成父类属性的初始化
    //子类的构造器就完成子类的初始化
    public PC(String cpu, String memory, String hardDisk, String brand) {
        super(cpu, memory, hardDisk);
        setBrand(brand);
    }

    public String getBrand() {
        return brand;
    }

    public void setBrand(String brand) {
        this.brand = brand;
    }

    //打印电脑信息
    public void printInfo(){
        System.out.println("Computer's info:\n"+ getDetails() + "\nBrand:" +brand);
    }
}

NotePad类

package com.hspedu.extend_.Exercise;

public class NotePad extends Computer {
    private String color;

    public NotePad(String cpu, String memory, String hardDisk, String color) {
        super(cpu, memory, hardDisk);
        setColor(color);
    }

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }

    public void printInfo(){
        System.out.println("Computer's info:\n"+ getDetails() + "\nBrand:" +color);
    }
}

Test类

package com.hspedu.extend_.Exercise;

public class Test {
    public static void main(String[] args) {
        PC pc = new PC("AMD rx5800","金士顿 DDR4 8G 3200GHZ"
                        ,"金士顿 SSD 512GB" ,"戴尔");
        pc.printInfo();
        System.out.println("====NotePad====");
        NotePad notePad = new NotePad("AMD rx3600x", "七彩虹 DDR4 8G 3200GHZ"
                , "三星 SSD 512GB", "华硕");
        notePad.printInfo();
    }
}

运行效果

image-20220128180051824