zoukankan      html  css  js  c++  java
  • 详解 继承(上)—— 工具的抽象与分层

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

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

    上面这一段话,并不是为了瞎扯才写出来的,上述的思想就是本人对于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关键字 与 多态》

  • 相关阅读:
    十一、docker仓库
    十、Docker容器:磁盘&内存&CPU资源限制实战
    八、docker的跨主机网络通信--flanneld
    九、dockerfile制作docker 镜像
    七、自己定制一个docker镜像
    六、docker的数据卷
    五、docker容器的网络访问
    四、docker容器的操作
    三、docker的镜像操作
    商品SKU
  • 原文地址:https://www.cnblogs.com/codderYouzg/p/12416403.html
Copyright © 2011-2022 走看看