详解 继承(上)—— 工具的抽象与分层

本篇博文讲解的知识点比较实用,但是,相关知识点太多,所以本人将内容分为上下两册,
那么,本人就不多废话,直接进入主题进行讲解了!

说到“继承”,大家可能都会想到我们日常中对于这个词的定义:将先人的 物品 或 意志 传承给后人,而后人也可以“择优继承”,并在先人的基础上产生 新的物品 或 新的意志。

上面这一段话,并不是为了瞎扯才写出来的,上述的思想就是本人对于JAVA中的“继承”的一种通俗的理解:
将父类的 成员 或 方法 传承给 子类 , 而子类也可以选择自己声明一个同名的成员,或者 一个同名、同返回值、同参数的方法,并在父类的基础上 定义 新的成员 或 新的方法 。

通过这样描述,可能大家会对于继承的优点就有了基本的认识。
那么,现在,本人来总结一下 继承的优点

继承的优点

  • 提高了代码的复用性
  • 提高了代码的维护性
  • 让类与类之间产生了关系,是多态的前提

在这里,本人还要提出的一点是:

Object类 是 所有类的基类(即 父类)

这样一来,想必同学们对于这个知识点就有了大致的认识了,那么,现在本人来编写一段代码来实现一下上述的思想:
首先,先在com.mec.about_inheritance.classes包下,来编写一个 Parent.java 文件:

package com.mec.about_inheritance.classes;

public class Parent {
    public int parentPublicMember;
    private int parentPrivateMember;
    protected int parentProtectedMember;
    int parentNoneMember;
    
    public Parent() {
        parentPublicMember = 1;
        parentPrivateMember = 2;
        parentProtectedMember = 3;
        System.out.println("Parent 无参构造方法");
    }
    
    public int parentPublicMethod() {
        parentPrivateMethod();
        System.out.println("执行Parent 类的 public 构造方法!");
        return parentPrivateMember;
    }
    
    private void parentPrivateMethod() {
        System.out.println("执行Parent 类的 private 构造方法!");        
    }
    
    protected void parentProtectedMethod() {
        System.out.println("执行Parent 类的 protected 构造方法!");      
    }
    
    void parentNoneMethod() {
        System.out.println("执行Parent 类的 无修饰 构造方法!");                
    }
}

现在,我们在本包(com.mec.about_inheritance.classes)下,来编写它的子类——Child.java :

package com.mec.about_inheritance.classes;

public class Child extends Parent {
    public Child() {
        this.   //这里的代码我们还没敲完就能看到下图现象:
    }
}

详解 继承(上)—— 工具的抽象与分层我们能够观察到:它的父类的所有 无修饰 和 用protected、public修饰词修饰的成员 和 方法,在本类中可以调用!

那么,现在我们创建一个新的包com.mec.about_inheritance.test,在这个包下建立 Parent类 的 包外子类 Son类:

package com.mec.about_inheritance.test;

import com.mec.about_inheritance.classes.Parent;

public class Son extends Parent {
    public Son() {
        this.   //这里的代码我们还没敲完就能看到下图现象:
    }
}

详解 继承(上)—— 工具的抽象与分层我们能够观察到:它的父类的所有 用protected、public修饰词修饰的成员 和 方法,在本类中可以调用!

那么,现在我们创建一个新的包com.mec.about_inheritance.test,在这个包下建立 Parent类 的 包外非子类 Demo类:

package com.mec.about_inheritance.demo;

import com.mec.about_inheritance.classes.Child;
import com.mec.about_inheritance.classes.Parent;
import com.mec.about_inheritance.test.Son;

public class Demo {

    public static void main(String[] args) {
        Parent parent = new Parent();
        Child child = new Child();
        Son son = new Son();
        
        parent.     //这里的代码我们还没敲完就能看到下图现象:
    }

}

详解 继承(上)—— 工具的抽象与分层我们能够观察到:它调用的类的所有 用public修饰词修饰的成员 和 方法,在本类中可以调用!

讲到这里,相信好多同学都已经懵了,毕竟本人也是从学习这个知识点的时期过来的,为了方便同学们对比这几种的区别,本人现在将其总结罗列到一张表中:
权限修饰符 总结
| | 继承关系| 继承关系| 非派生类引用关系 |非派生类引用关系 |
|--|--|--|--|--|
| | 包内子类 |包外子类 | 包内其他类 | 包外其他类 |
|public | 能 | 能 | 能 | 能 |
| private | 否 | 否 |否 | 否 |
|protected | 能 | 能 | 能 | 否 |
| default (或 无修饰) |能 | 否 | 能 | 否 |

那么,本人现在来介绍下,这些 权限修饰符 的一般使用标准吧:
1.凡是打算为子类继承的成员和方法,用 protected 修饰;
2.不打算被 包外的类 引用的 成员 和 方法 ,不用写任何 权限修饰符 。

我们之前说过,在我们构建一个比较大的JAVA工程时,一般都会用到 “构造方法”。
那么,现在,本人来讲解一下 继承关系 中的 构造方法
我们还是通过代码的运行结果来总结结论:
首先,在 com.mec.about_inheritance.constructor 包下建立 Grandfather 类:

package com.mec.about_inheritance.constructor;

public class Grandfather {
    public Grandfather() {
        System.out.println("执行爷爷构造方法!");
    }
}

其次,我们在本包( com.mec.about_inheritance.constructor )下建立Parent 类:

package com.mec.about_inheritance.constructor;

public class Parent extends Grandfather {
    public Parent() {
        System.out.println("执行爸爸构造方法!");
    }
}

然后,我们在本包( com.mec.about_inheritance.constructor )下建立Child 类:

package com.mec.about_inheritance.constructor;

public class Child extends Parent{
    public Child() {
        System.out.println("执行孩子构造方法!");
    }
}

最后,我们建立一个新的包 com.mec.about_inheritance.constructor.test ,并在这个包下建立 Test类:

package com.mec.about_inheritance.constructor.test;

import com.mec.about_inheritance.constructor.Child;

public class Test {

    public static void main(String[] args) {
        new Child();
    }
}

然后,我们来观察下运行结果:
详解 继承(上)—— 工具的抽象与分层由此,我们可以看出,构造方法 的执行顺序
有当前类开始,根据继承关系,追溯到祖先类,再从上往下执行构造方法

但是,本人在之前的博文中说过,若一个类没有定义无参构造方法,则JVM会默认执行一个无参构造方法。但是,在继承这里,正是由于这个原因,会出现一些错误,如下:
我们现在对 Grandfather类 进行如下改变:

package com.mec.about_inheritance.constructor;

public class Grandfather {
    private int one;
    private int two;
    
    public Grandfather(int one, int two) {
        this.one = one;
        this.two = two;
        System.out.println("执行爷爷构造方法!");
    }

    public int getOne() {
        return one;
    }

    public void setOne(int one) {
        this.one = one;
    }

    public int getTwo() {
        return two;
    }

    public void setTwo(int two) {
        this.two = two;
    }
    
}

但是,就在这时,我们能够发现,Parent类那里竟然出现了错误:
详解 继承(上)—— 工具的抽象与分层错误提示说:父类Parent 的无参构造方法未定义,Parent类 无参构造方法必须执行另一种 父类 的构造方法。
简单来讲,就是说:因为Grandfather 类没有无参构造方法。要 Parent 执行 另一种 父类构造方法。
其实,Grandfather 类并不是没有构造方法,只是没有无参构造方法!
所以,这里执行 Grandfather 类的双参构造方法!

现在,本人对 Parent类 做如下改变:

package com.mec.about_inheritance.constructor;

public class Parent extends Grandfather {
    public Parent() {
        super(0, 0);
        System.out.println("执行爸爸构造方法!");
    }
}

详解 继承(上)—— 工具的抽象与分层
可以看到,现在没有问题了!

由上面的代码展示,我们可以看出继承有如下特点

继承的特点

  • Java只支持单继承,不支持多继承(即 一个类只能拥有一个父类)
  • Java支持 多层继承(继承体系)

但是,虽然这样很方便,继承也是存在着条件的:

  1. 子类只能继承父类所有非私有的成员(成员方法和成员变量)
  2. 子类不能继承父类的构造方法,但是可以通过super(待会儿讲)关键字去访问父类构造方法
  3. 不要为了 部分功能 而去 继承

那么,在本篇博文的末尾,本人要提出的一点是:我们虽然可以用“继承”提高代码的复用性,
但是,“继承”同样存在很大的弊端

继承的弊端: 使得 类的耦合性增强

这违背了我们的开发原则之一的 —— 高内聚,低耦合
(所谓“耦合”—— 类与类的关系
所谓 “内聚”—— 自己完成某件事情的能力)

相信看到这的同学们,一定对于super(0, 0) 这一行代码十分好奇吧,那么,请观看本人的下半篇博文——《详解 继承(下)—— super关键字 与 多态》

上一篇:Day 1 : All about servers


下一篇:(cheer you up)vue-router重点来袭