在《Think in java》中有这样一句话:复用代码是Java众多引人注目的功能之一。但要想成为极具革命性的语言,仅仅能够复制代码并对加以改变是不够的,它还必须能够做更多的事情。在这句话中最引人注目的是“复用代码”,尽可能的复用代码使我们程序员一直在追求的,现在我来介绍一种复用代码的方式,也是java三大特性之一---继承。

继承

在讲解之前我们先看一个例子,该例子是前篇博文(java提高篇-----理解java的三大特性之封装)的。

从这里我们可以看出,Wife、Husband两个类除了各自的husband、wife外其余部分全部相同,作为一个想最大限度实现复用代码的我们是不能够忍受这样的重复代码,如果再来一个小三、小四、小五……(扯远了!)我们是不是也要这样写呢?那么我们如何来实现这些类的可复用呢?利用继承!!

首先我们先离开软件编程的世界,从常识中我们知道丈夫、妻子、小三、小四…,他们都是人,而且都有一些共性,有名字、年龄、性别、头等等,而且他们都能够吃东西、走路、说话等等共同的行为,所以从这里我们可以发现他们都拥有人的属性和行为,同时也是从人那里继承来的这些属性和行为的。

从上面我们就可以基本了解了继承的概念了,继承是使用已存在的类的定义作为基础建立新类的技术,新类的定义可以增加新的数据或新的功能,也可以用父类的功能,但不能选择性地继承父类。通过使用继承我们能够非常方便地复用以前的代码,能够大大的提高开发的效率。

对于Wife、Husband使用继承后,除了代码量的减少我们还能够非常明显的看到他们的关系。

继承所描述的是“is-a”的关系,如果有两个对象A和B,若可以描述为“A是B”,则可以表示A继承B,其中B是被继承者称之为父类或者超类,A是继承者称之为子类或者派生类。

实际上继承者是被继承者的特殊化,它除了拥有被继承者的特性外,还拥有自己独有得特性。例如猫有抓老鼠、爬树等其他动物没有的特性。同时在继承关系中,继承者完全可以替换被继承者,反之则不可以,例如我们可以说猫是动物,但不能说动物是猫就是这个道理,其实对于这个我们将其称之为“向上转型”,下面介绍。

诚然,继承定义了类如何相互关联,共享特性。对于若干个相同或者相识的类,我们可以抽象出他们共有的行为或者属相并将其定义成一个父类或者超类,然后用这些类继承该父类,他们不仅可以拥有父类的属性、方法还可以定义自己独有的属性或者方法。

同时在使用继承时需要记住三句话:

1、子类拥有父类非private的属性和方法。

2、子类可以拥有自己属性和方法,即子类可以对父类进行扩展。

3、子类可以用自己的方式实现父类的方法。(以后介绍)。

综上所述,使用继承确实有许多的优点,除了将所有子类的共同属性放入父类,实现代码共享,避免重复外,还可以使得修改扩展继承而来的实现比较简单。

诚然,讲到继承一定少不了这三个东西:构造器、protected关键字、向上转型。

构造器

通过前面我们知道子类可以继承父类的属性和方法,除了那些private的外还有一样是子类继承不了的---构造器。对于构造器而言,它只能够被调用,而不能被继承。 调用父类的构造方法我们使用super()即可。

对于子类而已,其构造器的正确初始化是非常重要的,而且当且仅当只有一个方法可以保证这点:在构造器中调用父类构造器来完成初始化,而父类构造器具有执行父类初始化所需要的所有知识和能力。

public class Person {

protected String name;

protected int age;

protected String sex;

Person(){

System.out.println("Person Constrctor...");

}

}

public class Husband extends Person{

private Wife wife;

Husband(){

System.out.println("Husband Constructor...");

}

public static void main(String[] args) {

Husband husband = new Husband();

}

}

Output:

Person Constrctor...

Husband Constructor...

通过这个示例可以看出,构建过程是从父类“向外”扩散的,也就是从父类开始向子类一级一级地完成构建。而且我们并没有显示的引用父类的构造器,这就是java的聪明之处:编译器会默认给子类调用父类的构造器。

但是,这个默认调用父类的构造器是有前提的:父类有默认构造器。如果父类没有默认构造器,我们就要必须显示的使用super()来调用父类构造器,否则编译器会报错:无法找到符合父类形式的构造器。

public class Person {

protected String name;

protected int age;

protected String sex;

Person(String name){

System.out.println("Person Constrctor-----" + name);

}

}

public class Husband extends Person{

private Wife wife;

Husband(){

super("chenssy");

System.out.println("Husband Constructor...");

}

public static void main(String[] args) {

Husband husband = new Husband();

}

}

Output:

Person Constrctor-----chenssy

Husband Constructor...

所以综上所述:对于继承而已,子类会默认调用父类的构造器,但是如果没有默认的父类构造器,子类必须要显示的指定父类的构造器,而且必须是在子类构造器中做的第一件事(第一行代码)。

protected关键字

private访问修饰符,对于封装而言,是最好的选择,但这个只是基于理想的世界,有时候我们需要这样的需求:我们需要将某些事物尽可能地对这个世界隐藏,但是仍然允许子类的成员来访问它们。这个时候就需要使用到protected。

对于protected而言,它指明就类用户而言,他是private,但是对于任何继承与此类的子类而言或者其他任何位于同一个包的类而言,他却是可以访问的。

public class Person {

private String name;

private int age;

private String sex;

protected String getName() {

return name;

}

protected void setName(String name) {

this.name = name;

}

public String toString(){

return "this name is " + name;

}

/** 省略其他setter、getter方法 **/

}

public class Husband extends Person{

private Wife wife;

public String toString(){

setName("chenssy"); //调用父类的setName();

return super.toString(); //调用父类的toString()方法

}

public static void main(String[] args) {

Husband husband = new Husband();

System.out.println(husband.toString());

}

}

Output:

this name is chenssy

从上面示例可以看书子类Husband可以明显地调用父类Person的setName()。

诚然尽管可以使用protected访问修饰符来限制父类属性和方法的访问权限,但是最好的方式还是将属性保持为private(我们应当一致保留更改底层实现),通过protected方法来控制类的继承者的访问权限。

向上转型

在上面的继承中我们谈到继承是is-a的相互关系,猫继承与动物,所以我们可以说猫是动物,或者说猫是动物的一种。这样将猫看做动物就是向上转型。如下:

public class Person {

public void display(){

System.out.println("Play Person...");

}

static void display(Person person){

person.display();

}

}

public class Husband extends Person{

public static void main(String[] args) {

Husband husband = new Husband();

Person.display(husband); //向上转型

}

}

在这我们通过Person.display(husband)。这句话可以看出husband是person类型。

将子类转换成父类,在继承关系上面是向上移动的,所以一般称之为向上转型。由于向上转型是从一个叫专用类型向较通用类型转换,所以它总是安全的,唯一发生变化的可能就是属性和方法的丢失。这就是为什么编译器在“未曾明确表示转型”活“未曾指定特殊标记”的情况下,仍然允许向上转型的原因。

谨慎继承

上面讲了继承所带来的诸多好处,那我们是不是就可以大肆地使用继承呢?送你一句话:慎用继承。

首先我们需要明确,继承存在如下缺陷:

1、父类变,子类就必须变。

2、继承破坏了封装,对于父类而言,它的实现细节对与子类来说都是透明的。

3、继承是一种强耦合关系。

所以说当我们使用继承的时候,我们需要确信使用继承确实是有效可行的办法。那么到底要不要使用继承呢?《Think in java》中提供了解决办法:问一问自己是否需要从子类向父类进行向上转型。如果必须向上转型,则继承是必要的,但是如果不需要,则应当好好考虑自己是否需要继承。

慎用继承!!!!!!!!!!!!!!!!!!!!!!!!!!!

道一声java技术_java提高篇(二)-理解java的三大特性之继承 - Java 技术驿站-Java 技术驿站...相关推荐

  1. java 集成_java提高篇(二)-----理解java的三大特性之继承

    在<Think in java>中有这样一句话:复用代码是Java众多引人注目的功能之一.但要想成为极具革命性的语言,仅仅能够复制代码并对加以改变是不够的,它还必须能够做更多的事情.在这句 ...

  2. 【转】java提高篇(二)-----理解java的三大特性之继承

    [转]java提高篇(二)-----理解java的三大特性之继承 原文地址:http://www.cnblogs.com/chenssy/p/3354884.html 在<Think in ja ...

  3. Java提高篇 —— Java三大特性之继承

    一.前言 在<Think in java>中有这样一句话:复用代码是Java众多引人注目的功能之一.但要想成为极具革命性的语言,仅仅能够复制代码并对加以改变是不够的,它还必须能够做更多的事 ...

  4. java三大特性 继承_java基础(二)-----java的三大特性之继承

    在<Think in java>中有这样一句话:复用代码是Java众多引人注目的功能之一.但要想成为极具革命性的语言,仅仅能够复制代码并对加以改变是不够的,它还必须能够做更多的事情.在这句 ...

  5. 第十篇:面向对象系列之三大特性(二)

    本篇主要介绍面向对象的三大特性及 封装.继承.多态. 一.封装 第一层意义上的封装: 封装:从封装本身的理解,装 -- 将一系列东西(苹果.梨子.香蕉等)一股脑的塞进一个盒子内,而封--自然就是密封, ...

  6. java上转型对象特点_Java 浅析三大特性之一继承

    上文Java 浅析三大特性之一封装我们说到Java是一个注重编写类,注重于代码和功能复用的语言.Java实现代码复用的方式有很多,这里介绍一个重要的复用方式--继承. 在介绍继承之前,我们要明确一点, ...

  7. Day55-每日一道Java面试题-Java 面向对象编程三大特性: 封装 继承 多态

    Java 面向对象编程三大特性: 封装 继承 多态 封装 封装把一个对象的属性私有化,同时提供一些可以被外界访问的属性的方法,如果属性不想被外界访问,我们大可不必提供方法给外界访问.但是如果一个类没有 ...

  8. java long常量池_Java提高篇之常量池

    一.相关概念 1. 什么是常量 用final修饰的成员变量表示常量,值一旦给定就无法改变! final修饰的变量有三种:静态变量.实例变量和局部变量,分别表示三种类型的常量. 2. Class文件中的 ...

  9. java提高篇四_(转)java提高篇(四)-----理解java的三大特性之多态

    面向对象编程有三大特性:封装.继承.多态. 封装隐藏了类的内部实现机制,可以在不影响使用的情况下改变类的内部结构,同时也保护了数据.对外界而已它的内部细节是隐藏的,暴露给外界的只是它的访问方法. 继承 ...

  10. 多态java_java提高篇(四)-----理解java的三大特性之多态

    面向对象编程有三大特性:封装.继承.多态. 封装隐藏了类的内部实现机制,可以在不影响使用的情况下改变类的内部结构,同时也保护了数据.对外界而已它的内部细节是隐藏的,暴露给外界的只是它的访问方法. 继承 ...

最新文章

  1. 专访中国移动钱岭:大数据更像是一种“倍增器”
  2. Hibernate---进度1
  3. Stanford UFLDL教程 深度网络概览
  4. 淮阳一高2021高考成绩查询,周口教育网2021年淮阳中招成绩查询系统
  5. SpringBoot-JPA的查询语言详解
  6. 使用Lubuntu开发Android应用
  7. 广度优先遍历算法-02合法的括号问题
  8. (转)微服务框架落地实践之路
  9. 洛谷 CSP2019-J2 自测 P5661 公交换乘
  10. mysql导入sql文件乱码或者报错unknown command
  11. 修改JDK的经历:两处字体的粗体代码引起的错误
  12. Vasp学习专题之软件的基本功能和使用
  13. opendrive文件结构
  14. matlab 自写 自适应中值滤波 matlab自适应中值滤波算法
  15. 仿美洽客服系统-gin框架内核独立自主源码开发在线客服系统
  16. Python 用Pygame写一个Flappy Bird经典小游戏
  17. 一文读懂生成对抗网络(GANs)【下载PDF | 长文】
  18. 数据标注工具下载中遇到的各种问题
  19. 人脸扫描建模_一种基于三维扫描数据的人脸建模方法
  20. 什么是数据规约,数据规约的策略都有哪些

热门文章

  1. 爆赞,java后端开发路线。
  2. RN开发模型,供参考
  3. linux readelf,readelf命令常用参数介绍
  4. NP实验-1 华为MSTP+VRRP练习题
  5. python游戏设计的课题背景_游戏设计论文开题报告
  6. Charles抓包工具简单教程
  7. Linux下C语言开发(多任务编程之任务、进程、线程)
  8. ztree 自定义参数_jQuery Ztree基本用法
  9. Google Chrome 浏览器离线安装包下载方法
  10. VUE day_08(7.26)学子商城项目详细版