Java - 19 面向对象编程的三大特征:继承

wxrwajiez / 2024-10-19 / 原文

Java - 19 面向对象编程的三大特征:继承

  • 解决代码复用,维护性,扩展性

  • 多个类存在相同的属性和方法时,可以从这些类中抽象出父类,在父类中定义这些相同的属性和方法,所有子类不需要重新定义这些属性和方法,只需要通过extends来声明继承父类即可

e.g.

public class Test{
    public static void main(String[] args){
        Pupil p = new Pupil();
        p.name = "w";
        p.age = 12;
        p.testing();
        p.setScore(100);
    }
}
class Student{
    public String name;
    public int age;
    private double score;
    
    public void setScore(double score){
        this.score = score;
    }
}

class Pupil extends Student{
    public void testing(){
        System.out.println("小学生 " + name + " 正在考试");
    }
}
class Graduate extends Student{
    public void testing(){
        System.out.println("大学生 " + name + " 正在考试");
    }    
}

细节

  1. 子类继承所有的属性和方法,但私有属性和方法不能直接访问,要通过公共方法去访问 (getXxx)

在同一个包中:子类可以访问父类中用默认修饰符声明的属性和方法

在不同包中:子类无法访问父类中用默认修饰符声明的属性和方法

  1. 子类创建对象时一定会调用父类的构造器,完成父类的初始化

  2. 不管子类使用哪个构造器,默认情况下总会调用父类的无参构造器,如果父类没有无参构造器,则必须在子类的构造器中用 super 去指定使用父类的哪个构造器完成对父类的初始化工作

  3. 如果希望指定使用父类的某个构造器,显式地调用ta

class Base{
    public String name;
    private int age;
    
    public Base(){
        
    }
    public Base(String name){
    	this.name = name;
    }
    public Base(String name, int age){
    	this.name = name;
        this.age = age;
    }
}

class Sub extends Base{
    public Sub(){
        super(); // 父类的无参构造器
        // 什么都不写也可以
    }
    public Sub(String name){
        super(name);
    }
    public Sub(String name, int age){
        super(name, age);
    }
}
  1. super 在使用时,必须放在子类构造器的第一行,只能在构造器中使用
  2. super() this() 都必须放在构造器第一行,所以不能共存
  3. Java中,Object 是所有类的基类
  4. 父类构造器的调用不限于直接父类,将一直往上追溯到Object
  5. 单继承机制:子类最多只能直接继承一个父类
  6. 不能滥用继承,必须满足 is - a 逻辑

继承本质分析

继承的本质就是建立查找关系

加载过程 Obeject -> GrandPa -> Father -> Son

cal();

练习

class B extends A{
    B(){
        this.("abc");
    }
    B(String name){
        
    }
}

class B extends A{
    B(){
        this.("abc"); // this 和 super 只能存在一个,所以这里不会调用A的默认构造方法
    }
    B(String name){
        // super(); 被隐藏,会调用父类A的默认构造方法
    }
}

super细节

super代表父类的引用,用于访问父类的属性,方法,构造器

  • 访问父类的属性,但不能访问父类的private属性

  • 访问父类的方法,但不能访问父类的private方法

  • 访问父类的构造器,只能放在构造器的第一句

好处

分工明确:父类属性由父类初始化,子类属性由子类初始化

重名成员(属性和方法)访问:重名时,必须使用super访问父类成员,没有重名,super, this, 直接访问是一样的

super.cal(); // 不找本类,其它逻辑一样

方法覆盖(重写)

子类有一个方法和父类的某个方法名称,返回类型,参数一样

细节

  • 形参列表,方法名称 要完全一致
  • 子类方法的返回类型和父类方法返回类型一样,或是父类返回类型的子类
  • 子类方法不能缩小父类方法的访问权限

对比重载(overload)和重写(override)