美文网首页
16.面向对象进阶:继承,重写,构造器访问,成员访问,this&

16.面向对象进阶:继承,重写,构造器访问,成员访问,this&

作者: 每天起床都想摆 | 来源:发表于2022-01-20 23:07 被阅读0次

面向对象三大基本特征之二:继承

继承概述

  • 继承是类与类之间的一种关系

  • 多个类继承单独的某个类,多个类就可使用单独的这个类的属性和行为了;Java中子类更强大

  • 多个类称为子类(又称派生类),单独的这个类称为父类(又称基类,或超类)

  • 使用extends关键字实现继承:public class 子类名 extends 父类名()

    public class Student extends People{}
    //表示Student类继承自People类
    
  • 使用继承的好处:提高代码复用,减少代码冗余,增强类的功能扩展性

  • 测试代码:

    package com.java.test;
    
    public class Student2 extends People {
    
        public void study() {
            System.out.println(getName() + "读书学习");
        }
    }
    
    
    package com.java.test;
    
    public class Teacher extends People {
    
        public void teach() {
            System.out.println(getName() + "教书育人");
        }
    
    }
    
    package com.java.test;
    
    public class People {
        private String name;
        private int age;
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    }
    
    
    package com.java.test;
    
    public class TestExtends {
        public static void main(String[] args) {
            Student2 student = new Student2();
            Teacher teacher = new Teacher();
            student.setName("徕卡");
            student.setAge(23);
            teacher.setName("哈苏");
            teacher.setAge(32);
            System.out.println(student.getName() + "\t" + student.getAge());
            System.out.println(teacher.getName() + "\t" + teacher.getAge());
    
            student.study();
            teacher.teach();
        }
    }
    

继承的设计规范,内存运行原理

继承设计规范

  • 子类们相同特征(共性属性,共性方法)放在父类中定义;子类独有的属性和行为应该定义在子类自己里面

    如果子类独有的属性,行为定义在父类中,会导致其他子类也会得到这些属性和行为,这不符合面向对象逻辑

内存运行原理

  • 首先加载主方法时会在堆内存中开辟空间,在空间中划分出一块父类空间(称为super)和一块子类空间(称为this)
  • image.png

继承的特点(面试热点)

  1. 子类可以继承父类的属性和行为,但是子类不能继承父类的构造器

    • 子类有自己的构造器,父类构造器用于初始化父类对象

    • 子类是否可以继承父类私有的成员(存在争议)

      • Java官方文档的解释:子类不能继承父类的私有成员,但是如果子类中公有的方法影响到了父类私有成员,那么私有成员是能够被子类使用的

      • 个人理解:当存在一个子类对象时,在内存空间上:子类对象继承的super中私有成员被继承但是无法直接访问

      image.png
    • 子类是否可以继承父类的静态成员(存在争议)

      • 子类可以直接使用父类的静态成员(共享并非继承)

        静态的成员属于类本身,且静态只会加载一次,静态是属于父类的关系,即子类不能继承父类的静态成员,这种关系是父类向子类共享静态成员,子类可以共享访问使用静态成员,但是并非继承关系

  2. Java是单继承模式,一个类只能继承一个直接父类

  3. Java不支持多继承,但是支持多层继承

  4. Java中所有的类都是Object类的子类

继承后:成员变量,成员方法的访问特点

  • 在子类方法中访问成员变量,成员方法时,满足:就近原则

    就近原则:

    • 先子类局部范围找
    • 然后子类成员范围找
    • 然后父类成员范围找,如果父类范围还没有找到则报错
  • 使用super关键字访问父类的成员

  • 当子类和父类中出现了同名的方法,会优先使用子类同名方法,此时要使用父类中的同名方法的办法是在子类中建立中转方法

  • 测试代码

    package com.java.test;
    
    public class ExtendsDemo {
        public static void main(String[] args) {
            Wolf w = new Wolf();
            System.out.println(w.name);
            w.showName();
            w.dance();  //触发子类的dance方法
            //  调用中转方法来触发父类的dance方法
            w.sing();
        }
    }
    
    class Animal {
        public String name = "触发父类";
    
        public void dance() {
            System.out.println("父类dance方法触发");
        }
    }
    
    class Wolf extends Animal {
        public String name = "触发子类";
    
        public void showName() {
            String name = "局部名称";
            System.out.println(name);   //  局部名称
            System.out.println(this.name);  //  触发子类
            System.out.println(super.name); //  触发父类
        }
    
        public void dance() {
            System.out.println("子类dance方法触发");
        }
    
        public void sing() {
            super.dance();  //sing为中转方法
        }
    }
    

继承后:方法重写

  • 在继承体系中,子类出现了和父类中一模一样的方法声明,我们称子类这个方法是重写的方法

  • 方法重写的应用场景:

    • 当子类需要父类的功能,但父类的该功能不完全满足自己的需求时
    • 子类可以重写父类中的方法
  • @Override重写注解:

    • 放在重写后的方法上,作为重写是否正确的校验注解
    • 加上该注解后如果重写错误,编译阶段会出现错误提示(例如方法名不一致时,可以防止运行的是新方法而不是重写)
    • 建议重写方法都加上@Override注解,代码安全,优雅!
  • 方法重写注意事项和要求

    • 重写方法的名称,形参列表必须与被重写方法的名称和参数列表一致

    • 私有方法被能重写(因为私有方法本身也不可以被访问)

    • 子类重写方法时,访问权限必须大于或等于父类

      按公开级别从大到小依次是:public > protected > 缺省

    • 子类不能重写父类的静态方法,如果重写会报错

      因为静态方法属于类,而重写的前提就是对被重写的方法拥有所有权,子类不曾拥有父类静态方法,所以对子类而言不存在对父类静态方法重写这个说法

  • 测试代码:

    package com.java.test;
    
    public class ReWrite {
        public void run() {
            System.out.println("跑步");
        }
    
        public void play() {
            System.out.println("打球");
        }
    
        public static void main(String[] args) {
            ReWrite2 re = new ReWrite2();
            re.run();
            re.play();
        }
    }
    
    class ReWrite2 extends ReWrite {
        @Override
        public void run() {
            super.run();    //重写时保留父类原方法中的功能
            System.out.println("马拉松");  //对父类中的方法进行重写
        }
    
        @Override
        public void play() {
            super.play();
            System.out.println("锦标赛");
        }
    }
    
    

继承后:子类构造器的特点

  • 子类中所有的构造器默认都会先访问父类中无参的构造器,再执行自己

    • 子类在初始化的时候,有可能会使用到父类中的数据,如果父类没有完成初始化,子类将无法使用父类的数据
    • 子类初始化之前,一定要调用父类构造器先完成父类数据空间的初始化
  • 如何调用父类构造器

    • 子类构造器的第一行语句默认都是:super(),不写也存在
  • 测试代码:

    package com.java.test;
    
    public class constructor {
        public static void main(String[] args) {
            worker w = new worker();
            /*
            父类构造器被触发
            子类构造器被触发
             */
    
        }
    }
    
    class boss {
        public boss() {
            System.out.println("父类构造器被触发");
        }
    }
    
    class worker extends boss {
        public worker() {
            super();    //默认的,写不写都有,默认就是找父类无参构造器
            System.out.println("子类构造器被触发");
        }
    }
    

继承后:子类构造器访问父类有参构造器

  • super调用父类有参构造器的作用:

    • 初始化继承自父类的数据
  • 父类中没有无参构造器,只有有参构造器,会出现什么情况

    • 报错,因为子类默认调用父类的无参构造器
  • 如何解决

    • 子类构造器中可以通过书写super(...),手动调用父类的有参构造器
  • 测试代码:

    package com.java.test;
    
    public class Constructor1 {
        public static void main(String[] args) {
            American a = new American("张三", 21, "男");
            System.out.println(a.getName());
            System.out.println(a.getAge());
            System.out.println(a.getSex());
        }
    }
    
    class English {
        private String name;
        private int age;
    
        // 有参构造器引发继承报错,选择了有参构造器时,建议加上无参构造器
        // 或者子类手动调用父类的有参构造器,即便如此,实际开发仍建议加上无参构造器
        public English(String name, int age) {
            this.name = name;
            this.age = age;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    }
    
    class American extends English {
        private String sex;
    
        // 手动调用父类的有参构造器
        public American(String name, int age, String sex) {
            super(name, age);
            this.sex = sex;
        }
    
        public String getSex() {
            return sex;
        }
    
        public void setSex(String sex) {
            this.sex = sex;
        }
    }
    
    

this,super使用总结

关键字 访问成员变量 访问成员方法 访问构造方法
this this.成员变量
访问本类成员变量
this.成员方法
访问本类成员方法
this(...)
访问本类构造器
super super.成员变量
访问父类成员变量
super.成员方法
访问父类成员方法
super(...)
访问父类构造器
  • this:代表本类对象的引用
  • super:代表父类存储空间的标识
  • 对于this(...)访问本类构造器

    案例代码:

    pubic class Student{
        private String schoolName;
        private String name;
        
        public Student(String name){
            this(name, "奥利奥")
        }
        
        public Student(String name, String schoolName){
            this.name = name;
            this.schoolName = schoolName;
        }
    }
    
  • this(...)和super(...)使用注意点
    • 子类通过this(...)去调用本类的其他构造器,本类其他构造器会通过super手动调用父类的构造器,最终还是会调用父类构造器的
    • this和super都只能放在构造器的第一行,所以也就意味着二者不可以共存在一个构造器中

相关文章

  • 16.面向对象进阶:继承,重写,构造器访问,成员访问,this&

    面向对象三大基本特征之二:继承 继承概述 继承是类与类之间的一种关系 多个类继承单独的某个类,多个类就可使用单独的...

  • 10.23学习总结

    今天继续学了面向对象程序设计,主要还是一些语法的学习,包括索引器,继承与派生,调用构造函数,成员访问权限,它们在c...

  • 王道程序员求职宝典(十二)面向对象编程

    面向对象编程 继承访问方式- 内部访问- 对象访问(外部访问)访问属性公有继承私有继承保护继承继承导致二义性类间转...

  • 构造器Constructor是否可被override

    构造器Constructor不能被继承,因此不能重写override 构造器是一个特殊的方法,可以有访问性质的修饰...

  • Java中的继承

    学习笔记 目录:一、继承的实现二、继承中成员变量、构造方法、成员方法访问特点1、继承中成员变量访问的特点2、继承中...

  • 重载(Overload)与重写(Override)

    重载与重写是Java面向对象编程的重要概念。 重写(Override)重写是子类继承父类后,对父类允许访问(子类有...

  • javascirpt复习

    实例中访问构造函数原型的指针,指向的是构造函数原型,不是构造函数; 所以重写构造函数原型对象,【实例对象】访问还是...

  • 面向对象(五)-面向对象三大特性之继承

    面向对象的三大特性 封装 继承 多态 1.封装 之前学习的构造函数与set、get访问器函数都是在进行封装。我们在...

  • 内存访问冲突,指针,逃逸闭包

    swift系列课程 子类继承父类 则子类的访问级别小于等于父类 子类成员重写 则子类重写成员要么大于等于子类访问级...

  • 继承 extends

    继承中成员变量的访问特点 1、父子类继承关系中,成员变量重名时,子类对象访问重名变量的2种方式 子类对象直接访问成...

网友评论

      本文标题:16.面向对象进阶:继承,重写,构造器访问,成员访问,this&

      本文链接:https://www.haomeiwen.com/subject/dbvshrtx.html