【Java】面向对象编程--继承

目录

一、介绍

二、使用细节

三、本质


一、介绍

  1. 继承是面向对象编程中的一种机制,它允许一个类(子类)从另一个类(超类或父类)继承属性和方法
  2. 当多个类存在相同属性(变量)和方法时,可以从中抽象出父类,父类中定义这些相同的属性和方法,通过 extends 继承父类,就可以使用其中的属性和方法


二、使用细节

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

/**
 * 子类继承了父类所有的属性和方法,非私有的属性和方法可以在子类直接访问
 * 私有属性和方法要通过父类提供公共的方法去访问
 */
public class Extends02 {
    public static void main(String[] args) {
        Sub sub1 = new Sub();
        sub1.sayOk();
    }
}

class Base {//父类
    public int b1 = 11;//公开属性
    protected int b2 = 22;//保护属性
    int b3 = 33;//默认属性
    private int b4 = 44;//私有属性

    public int getB4() {//公共方法返回 b4  因为b4 是private
        return b4;
    }

    public void Test111() {//公开方法
        System.out.println("方法 test111");
    }

    protected void Test222() {//保护方法
        System.out.println("方法 test222");
    }

    void Test333() {//默认方法
        System.out.println("方法 test333");
    }

    private void Test444() {//私有方法
        System.out.println("方法 test444");
    }

    public void getTest444() {//公共方法 因为Test444() 是private
        Test444();//调用Test444()
    }

}

class Sub extends Base {//子类

    public void sayOk() {//子类方法
        //非私有的属性和方法可以在子类直接访问
        System.out.println("b1=" + b1 + " b2=" + b2 + "  b3=" + b3);
        //但是私有属性和方法不能在子类直接访问
        //b4 是private 通过公共方法获取b4
        System.out.println("b4=" + getB4());

        Test111();
        Test222();
        Test333();
        //Test444();;错误
        //要通过父类提供公共的方法去访问
        getTest444();
    }
}
  • 子类调用自己的构造器时必须先调用父类的构造器, 完成父类的初始化
/**
 * 子类调用自己的构造器时必须先调用父类的构造器, 完成父类的初始化
 */
public class Extends02 {
    public static void main(String[] args) {
        Sub sub1 = new Sub();
    }
}

class Base {//父类

    public Base() {//无参构造器
        System.out.println("父类 Base() 无参构造器被调用");
    }

}

class Sub extends Base {//子类

    public Sub() {//无参构造器
        //super(); //编译器默认放置    默认调用父类的无参构造器
        System.out.println("子类 Sub() 无参构造器被调用");
    }
}
输出:
父类 Base() 无参构造器被调用
子类 Sub() 无参构造器被调用
  • 当创建子类对象时,不管使用子类的哪个构造器,默认情况下总会去调用父类的无参构造器,如果父类没有提供无参构造器,则必须在子类的构造器中用 super 去指定使用父类的哪个构造器完成对父类的初始化工作,否则,编译不会通过
/**
 * 当创建子类对象时,不管使用子类的哪个构造器,默认情况下总会去调用父类的无参构造器
 * 如果父类没有提供无参构造器,则必须在子类的构造器中用 super 去指定使用父类的哪个构造器
 * 完成对父类的初始化工作,否则,编译不会通过
 */
public class Extends02 {
    public static void main(String[] args) {
        Sub sub1 = new Sub("少爷");
    }
}

class Base {//父类

    public Base() {//无参构造器
        System.out.println("父类 Base() 无参构造器被调用");
    }

    public Base(String name) {
        System.out.println("父类 Base(String name) 构造器被调用");
    }

}

class Sub extends Base {//子类

    //当创建子类对象时,不管使用子类的哪个构造器,默认情况下总会去调用父类的无参构造器
    public Sub(String name) {
        // 默认情况下会调用父类的无参构造器
        // super()指定调用父类的Base(String name)构造器
        super("aaa");
        System.out.println("子类 Sub(String name)构造器被调用");
    }
}

输出:
父类 Base(String name) 构造器被调用
子类 Sub(String name)构造器被调用
  • 如果希望指定去调用父类的某个构造器,则显式的调用一下 : super(参数列表)
/**
 * 如果希望指定去调用父类的某个构造器,则显式的调用一下 : super(参数列表)
 */
public class Extends02 {
    public static void main(String[] args) {
        Sub sub1 = new Sub();
    }
}

class Base {//父类

    public Base() {//无参构造器
        System.out.println("父类 Base() 无参构造器被调用");
    }

    public Base(String name) {
        System.out.println("父类 Base(String name) 构造器被调用");
    }

    public Base(String name, int age) {
        System.out.println("父类 Base(String name ,int age) 构造器被调用");
    }

}

class Sub extends Base {//子类

    public Sub() {
        //1. 调用父类无参构造器
        super();//父类的无参构造器

        //2. 调用父类 Base(String name) 构造器
        super("少爷");

        //3. 调用父类 Base(String name, int age) 构造器
        super("龙部", 22);
    }
}

  1. super 在使用时,必须放在构造器第一行(super 只能在构造器中使用)
  2. super() 和 this() 都只能放在构造器第一行,因此这两个方法不能共存在一个构造器
  3. java 所有类都是 Object 类的子类, Object 是所有类的基类
  4. 父类构造器的调用不限于直接父类!将一直往上追溯直到 Object (顶级父类)
  5. 子类最多只能继承一个父类(指直接继承),即 java 中是单继承机制
  6. 不能滥用继承,子类和父类之间必须满足 is-a 的逻辑关系

三、本质

  • 当子类对象建立完后,建立查找关系

/**
 * 1.方法区加载类 先加载顶级类 后父子 然后子类
 * 2.堆里分配空间 先分配顶级类 后父子 然后子类  整个空间还是子类对象
 * 当属性为私有时 内存中也会有
 */
public class Extends03 {
    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);//输出 40
        System.out.println(son.hobby);//输出 盘串

        //当属性为不可访问时
        //调用公共方法返回 私有属性
        System.out.println(son.getHobby());//输出 跑步

        //当爷爷类中 含有hobby 属性  父亲类中也含有hobby 属性时
        //因为继承是查找关系
        //从孙子类开始查找hobby 属性 当找到父亲类中发现后不管是什么访问权限 都不会再到爷爷类中查找


    }
}

class GrandPa {
    String name = "爷爷";
    String hobby = "盘串";

}

class Father extends GrandPa {
    String name = "爸爸";
    int age = 40;

    private String hobby = "跑步";

    public String getHobby() {//公共方法返回 私有属性
        return hobby;
    }
}

class Son extends Father {
    String name = "孙子";

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值