面向对象系列之继承

这是我参与更文挑战的第5天,活动详情查看: 更文挑战

类继承

class 了解之后,我们考虑一个问题。如果两个 class,它们的变量和方法基本相同,仅仅是其中一个 class 会有一些自己特有的变量和方法,那么相同的那些变量和方法真的需要在两个 class 里都写一遍么?

比如一个表示学生的 class Student ,它相对于 class Person 只是多了一个分数 score 的成员变量,那还需要像下面这样,把 name 字段也定义一下么?

/**
 * 学生
 *
 * @author 蜗牛
 * @from 公众号:蜗牛互联网
 */
public class Student {

    /**
     * 名字
     */
    String name;

    /**
     * 分数
     */
    int score;

}
复制代码

这很明显带来了代码重复使用的问题!那能不能在 Student 中不写重复代码?

Java 里的继承这时候就派上用场了,继承是面向对象编程的一种强大机制,能够让子类继承父类的特征和行为,使得子类对象能够具有父类的实例变量和方法。

子类继承父类,父类派生子类。父类也叫基类,子类也叫派生类。

通常来讲,类的层次划分总是下一层比上一层更具体,并且包含上一层的特征,这样下层的类就能自动享有上层类的特点和性质。继承就是派生类自动地共享基类中成员变量和成员方法的机制。

在 Java 中,通过 extends 关键字实现继承,并且所有的类都是继承于 java.lang.Object ,所以这就是万物皆对象在 Java 里的真实写照。你可能会疑惑,自定义的类并没有 extends 关键字为什么还能继承 Object 呢?这是因为这个类在 java.lang 包里,Java 已经默认支持了。

package cn.java4u.oo;

/**
 * 学生
 *
 * @author 蜗牛
 * @from 公众号:蜗牛互联网
 */
public class Student extends Person {

    /**
     * 分数
     */
    int score;

}
复制代码

知道了继承的基础概念后,我们看下继承有啥作用?

首先,继承是能够自动传播代码和重用代码的有力工具。它能在已有类上扩充新类,减少代码的重复冗余,也因为冗余度降低,一致性就得到了增强,从而提升了程序的可维护性。

其次,继承可以清晰体现出类与类之间的层次结构关系,提升了代码的可读性。

另外,继承是单方向的,即派生类可以继承和访问基类成员,但反过来就不行。而且 Java 只允许单一继承,也就是一个派生类不能同时继承多个基类,这和 C++ 是不同的。

在使用继承的时候,还要考虑到基类成员的访问控制权限。可以参考封装那块内容的访问权限控制介绍。

子类实例化过程

特别要说明的是,父类的构造方法是不能被子类继承的,即便它是 public 的。父类的构造方法负责初始化属于它的成员变量,而子类的构造方法只需考虑自己特有的成员变量即可,不必关注父类状况。

package cn.java4u.oo.inherit;

/**
 * 定义父类
 *
 * @author 蜗牛
 * @from 公众号:蜗牛互联网
 */
public class Parent {


    /**
     * 构造方法
     */
    public Parent() {

        System.out.println("这是父类 Parent 的构造方法");
    }
}

package cn.java4u.oo.inherit;

/**
 * 定义子类
 *
 * @author 蜗牛
 * @from 公众号:蜗牛互联网
 */
public class Child extends Parent {

    /**
     * 构造方法
     */
    public Child() {

        System.out.println("这是子类 Child 的构造方法");

    }
}

package cn.java4u.test;

import cn.java4u.oo.inherit.Child;

/**
 * @author 蜗牛
 * @from 公众号:蜗牛互联网
 */
public class InheritTest {

    public static void main(String[] args) {

        Child child = new Child();
    }
}
复制代码

因此,在实例化子类的对象时,Java 先是执行父类的构造方法,然后执行子类的构造方法。如果父类还有更上级的父类,就会先调用更高父类的构造方法,再逐个依次地将所有继承关系的父类构造方法全部执行。如果父类的构造方法执行失败,则子类的对象也将无法实例化。

上边的代码运行后,会输出:

这是父类 Parent 的构造方法
这是子类 Child 的构造方法
复制代码

this 与 super

如果调用父类构造方法涉及到有参构造方法,可以使用 super 关键字来调用父类构造方法并传递参数。

说的 super,它还有一个能力,就是父类和子类的成员如果同名了,子类中默认只能访问自己的那个成员,想要访问父类成员,就可以通过 super.成员名 的语法实现。但这有个前提,就是父类的这个成员不能是 private 的。

super 相对的关键字是 thissuper 是指向当前对象的父类,而 this 是指向当前对象自己。this 常用来区别成员变量和局部变量,比如下面这段代码,我加了个有参构造方法。

public class Parent {

    int a;

    /**
     * 构造方法
     */
    public Parent() {

        System.out.println("这是父类 Parent 的构造方法");
    }

    public Parent(int a) {
        this.a = a;
    }


}
复制代码
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享