zoukankan      html  css  js  c++  java
  • Java——继承

    一、引入继承

    相同特征产生代码冗余,有如下俩个类(Java学生类和UI学生类)。

    // JavaStudent.java
    public class JavaStudent {
        private String number;   // 学号
        private String name;   // 姓名
        private int age;   // 年龄
        private String classes;   // 班级
        private String project;   // 项目
    
        // 考试
        public void exam(){
            System.out.println("学员考试");
        }
    
        // 登录
        public boolean login(String stuNo, String pwd){
            System.out.println("使用学号和密码登录");
            return true;
        }
    
        //...
    }
    
    // UIStudent.java 
    public class UIStudent {
        private String number;   // 学号
        private String name;   // 姓名
        private int age;   // 年龄
        private String classes;   // 班级
        private String opus;   // 作品
    
        // 考试
        public void exam(){
            System.out.println("学员考试");
        }
    
        // 登录
        public boolean login(String stuNo, String pwd){
            System.out.println("使用学号和密码登录");
            return true;
        }
    
        //...
    }
    

    经过观察俩个类可以发现,它们都有一些相同特征(相同的属性、相同的方法),比如相同的属性有学号、姓名、年龄、班级;相同的方法有考试和登录。

    针对上述发现问题,就有如下解决方案,就是把相同的属性和行为抽取出来,就可以降低重复代码的书写。抽取出来的共性代码单独封装到一个类中。

    二、什么是继承

    • 继承是将多个类的相同属性和行为抽取到单独一个类中,那么多个类无需再定义这些属性和行为,只要继承单独这个类即可使用这些属性和行为。
    • 多个类称为子类(派生类),单独的这个类称为父类(基类、超类)。

    三、继承的应用场景

    当多个类中有相同的代码(属性、行为)时,把相同的代码抽取出来,封装到了一个单独的类中,这样做的好处就是提高代码的复用性(可以重复使用)。

    但是这样做就面临一个问题,就是单独封装出来的类和之前被抽取代码的类,怎么建立关系(允许使用单独封装类中的成员)。接下来就解决这个问题。

    四、如何使用

    • 使用继承需要在俩个或者多个类之间
    • Java使用关键字extends表示继承

    五、语法格式

    public class 子类名 extends 父类名{
    
    }
    

    六、is a 

    在类与类之间建立继承关系时,必须符合 is a   // 是一个...

    要符合现实生活中的认知

    比如

    • Java学生是一个学生
    • 猫是一个动物
    • 冰箱是一个电器

    如果是如下就不符合了

    • Java学生是一个电器

    七、使用继承改造代码

    新增一个Student类,把JavaStudent类和UIStudent类中的相同特征进行抽取,如下

    // Student.java
    public class Student {
        private String number;   // 学号
        private String name;   // 姓名
        private int age;   // 年龄
        private String classes;   // 班级
    
        public String getNumber() {
            return number;
        }
    
        public void setNumber(String number) {
            this.number = number;
        }
    
        ...(其他属性get、set方法;Student空参构造方法、有参构造方法)
    
        // 考试
        public void exam(){
            System.out.println("考试");
        }
    
        // 登录
        public boolean login(String stuNo, String pwd){
            System.out.println("登录");
            return true;
        }
    }

    // JavaStudent.java public class JavaStudent extends Student{ private String project; // 项目 //...(project属性get、set方法、JavaStudent空参构造方法、有参构造方法) }

    // UIStudent.java
    public class UIStudent extends Student{
        private String opus;   // 作品
      //...(opts属性get、set方法、UIStudent空参构造方法、有参构造方法)
    }

    上述代码JavaStudent类和UIStudent类就继承了Student类,抽取完相同特征后,JavaStudent类和UIStudent类只保留了一些特有的特征。子类就可以访问父类的非私有成员。虽然此时JavaStudent类和UIStudent类不能直接访问父类的私有属性,但可以通过get、set方法进行访问。建立一个测试类验证,如下所示

    public class Test {
        public static void main(String[] args) {
            JavaStudent javaStu = new JavaStudent("阿里云盘");
            javaStu.setNumber("10010");
            javaStu.setName("张三");
            javaStu.setAge(27);
            javaStu.setClasses("302");
    
            System.out.println(javaStu.getName() + "---" + javaStu.getProject());   // 张三---阿里云盘
            javaStu.exam();   // 使用父类的方法打印——考试
        }
    }
    

    八、继承的使用规范

    工作中对于继承应该遵循如下规范

    • 多个类相同特征(共性属性、共性方法)放在父类中定义。
    • 子类扩展的属性和方法应该定义在本子类中。

    九、父子类的对比

    经过对比也可以发现如下特点

    • 子类和父类相比子类的功能更强大
    • 子类和父类先比父类的范围表示更广

      

    十、继承后子类对象的内存原理

    基于上述代码,当你在测试类(Test.java)中new一个子类(JavaStudent.java)的时候,系统就会在堆内存中开辟一块新的空间,这个空间就属于JavaStu这个对象,此时,这个空间一分为二,一块叫做父类成员空间——super,一块叫做子类成员空间——this。当我们这些考试方法时javaStu.exam(),会首先进入子类成员空间进行查找,结果是没有找到,接着会进入父类成员空间查找,结果找到了,就调用。

    总结如下:

    子类对象在创建时,在堆内存中开辟的空间包含了两部分内容

    • super空间:存储父类的相关成员
    • this空间:存储了子类自身的相关成员

    子类对象在访问成员时

    • 优先使用子类自己的成员,当子类没有该成员时,去super空间中使用父类的成员,如果父类也没有,会一直向上查找,如果直至Object类都没有的话,会报错。

    十一、继承的三个特点

    1. 单继承,只支持单继承,不支持多继承
    2. 一个父类可以有多个子类
    3. 多层继承,子类C继承父类B,父类B可以继承父类A。如果一个类没有直接继承关系,默认继承Object,因此,所有类都是Object类的子类。

    十二、继承中变量访问特点

     在子类方法中访问一个变量满足——就近原则

    1. 先子类局部范围找
    2. 然后子类成员范围找
    3. 然后父类成员范围找,如果父类范围内还没有找到则报错
    4. 父类中私有的成员子类不能直接访问

    如果局部变量、本类成员变量、父类成员变量重名,应该按照如下进行区分

    1. 局部变量直接访问
    2. 本类成员变量,使用this访问——this.本类成员变量
    3. 父类成员变量,使用super访问,super.父类成员变量
    4. 使用this.变量名时,如果子类没有找到,也会去父类进行查找

    十三、继承中方法访问特点

    通过子类对象对象访问一个方法也满足——就近原则

    1. 子类成员范围找
    2. 父类成员范围找
    3. 不能直接访问父类中私有成员

    如果子父类中出现同名参数的方法,先优先使用子类的,要访问父类相同方法可以使用super关键字,如super.父类成员方法

    十四、方法的重写

    1、方法的应用体现

    方法的应用体现有2种,如下

    1.1、重载

    有如下特点

    • 在同一个类中
    • 方法名相同
    • 参数列表不相同
    • 和方法返回值没有任何关系

    1.2、重写

    有如下特点

    • 在父子类中
    • 方法名相同
    • 参数列表相同
    • 方法返回值相同

     2、什么是方法重写

    重写就是子类对父类的方法逻辑进行重新编写,当然,这个方法得是子类可访问的实例方法。

    3、什么时候需要方法重写

    当子类需要父类的功能,但父类的该功能不能完全满足自己的需求时,子类可以重写父类中的方法,这样,即沿袭了父类的功能,又定义了子类特有的功能。

    4、如何快速重写一个方法

    声明不变,重新实现,重写时可以定义一个声明一样的方法,对方法体进行重新定义。

    如下,我有一个手机类,该类定义了一个方法就是打电话

    public class Phone {
        public void call(){
            System.out.println("通话中...");
        }
    }
    

    一段时间过后,该方法已经不能完全满足我的需求了,比如,我希望增加视频通话功能,此时,就可以新建一个类(NewPhone),继承自Phone类,对打电话功能(call)进行重写,如下 

    // NewPhone.java
    public class NewPhone extends Phone{
        public void call(){
            System.out.println("打开摄像头....");
    
            // 考虑到代码的复用性,可以使用super调用父类中的方法
            super.call();
        }
    }
    
    // Test.java 
    public class Test {
        public static void main(String[] args) {
            NewPhone newPhone = new NewPhone();
            newPhone.call();   // 打开摄像头....通话中...
        }
    } 
    

    5、@Override注解

    @Override注解是放在重写后的方法上,作为重写是否正确的校验注解,加上该注解后如果重写错误,编译阶段会出现错误提示。建议重写方法都加上@Override注解,代码安全、优雅。使用方式如下

    public class NewPhone extends Phone{
        @Override
        public void call(){
            System.out.println("打开摄像头....");
    
            // 考虑到代码的复用性,可以使用super调用父类中的方法
            super.call();
        } 
    }
    

    6、方法重写时的注意事项和要求

    1. 重写方法的名称和形参列表必须与被重写方法名称和参数列表一致
    2. 私有方法不能被重写
    3. 子类重写父类方法时,子类方法访问权限必须大于或者等于父类方法权限(缺省 < protected < public)

    十五、继承中构造方法的使用

    1、父类的构造方法会继承到子类吗

    不会。构造方法其方法名一定和类名一样,一个类不能存在一个和自己类名不同名的构造方法,但是,子类是可以使用父类的构造方法的,来初始化父类成员变量。

    2、子类该如何访问父类的构造方法

    在子类构造方法的第一句,使用super关键字访问。

    • super():访问父类无参构造方法(默认存在)
    • super(参数):访问父类有参构造方法,需要初始化父类中成员变量使用

    3、继承后子类构造器的执行流程是怎样的

    子类中任何一个构造方法执行时,都会先访问父类中的构造方法,然后再执行自己。如果子类构造方法没有显式调用父类构造方法,会默认调用父类的无参构造方法。

    所以,如果父类中没有无参数构造器,只有由参构造器,子类构造的话会报错,因为子类默认是调用父类无参构造器的。如下

    // Fat.java
    public class Fat {
        private String name;
    
        public Fat(String name) {
            this.name = name;
        }
    }
    
    // Son.java
    public class Son extends Fat{
        public Son() {   // 报错
        }
    
        public Son(String name) {
            super(name);
        }
    }
    

    如何解决上述问题,如下

    • 为父类添加无参构造方法
    • 在子类构造方法中,通过super,手动调用父类的有参构造方法

    十六 、super、this关键字使用总结

    1、使用场景梳理

    super、this同属于一个对象区别在于

    • this——代表本类对象的引用
    • super——代表父类存储空间的标识

    它们的使用格式如下

    关键字 访问成员变量 访问成员方法 访问构造方法
    this this.成员变量   // 访问本类成员变量 this.成员方法(...)   // 访问本类成员方法 this(...)   // 访问本类构造器
    super super.成员变量   // 访问父类成员变量 super.成员方法(...)   // 访问父类成员方法 super(...)   // 访问父类构造器

    2、this调用本类构造方法特点

    • 与super访问父类构造方法语法相似。需要在本类构造方法的第一句位置,格式——this(参数)
    • this不能调用自身构造方法,否则会陷入死递归
    • this和super调用构造方法不能共存
    • this调用本类构造方法的意义是——代码的复用,减少代码的冗余

    如下

    public class Cat {
        private String name;
        private int age;
    
        public Cat() {
            this("小白", 3);
        }
    
        public Cat(String name, int age) {
            this.name = name;
            this.age = age;
        }
    
        // get、set
    }
    

      

  • 相关阅读:
    分组声明
    描述项目的典型用户与场景
    用户调研
    10-11-12
    Sprint--5.21
    Cosplay之孩子的妈咪
    作业5.1之5.2
    51nod 1393 1393 0和1相等串
    51nod 1090 3个数和为0(排序+二分)
    51nod 1095 Anigram单词(map的使用)
  • 原文地址:https://www.cnblogs.com/xulinjun/p/14747684.html
Copyright © 2011-2022 走看看