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

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

继承

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

e831c74fb9b9d8824708e143aa557292.png

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

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

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

363d2dcce90e26b7bf4cc5deb2af387d.png

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

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

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

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

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

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

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

3、子类可以用自己的方式实现父类的方法。

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

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

构造器

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

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

1 public classPerson {2 protectedString name;3 protected intage;4 protectedString sex;5

6 Person(){7 System.out.println("Person Constrctor...");8 }9 }10

11 public class Husband extendsPerson{12 privateWife wife;13

14 Husband(){15 System.out.println("Husband Constructor...");16 }17

18 public static voidmain(String[] args) {19 Husband husband = newHusband();20 }21 }22

23 Output:24 Person Constrctor...25 Husband Constructor...

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

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

1 public classPerson {2 protectedString name;3 protected intage;4 protectedString sex;5

6 Person(String name){7 System.out.println("Person Constrctor-----" +name);8 }9 }10

11 public class Husband extendsPerson{12 privateWife wife;13

14 Husband(){15 super("chenssy");16 System.out.println("Husband Constructor...");17 }18

19 public static voidmain(String[] args) {20 Husband husband = newHusband();21 }22 }23

24 Output:25 Person Constrctor-----chenssy26 Husband Constructor...

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

protected关键字

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

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

1 public classPerson {2 privateString name;3 private intage;4 privateString sex;5

6 protectedString getName() {7 returnname;8 }9

10 protected voidsetName(String name) {11 this.name =name;12 }13

14 publicString toString(){15 return "this name is " +name;16 }17

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

19 }20

21 public class Husband extendsPerson{22 privateWife wife;23

24 publicString toString(){25 setName("chenssy"); //调用父类的setName();

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

27 }28

29 public static voidmain(String[] args) {30 Husband husband = newHusband();31

32 System.out.println(husband.toString());33 }34 }35

36 Output:37 this name is chenssy

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

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

向上转型

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

1 public classPerson {2 public voiddisplay(){3 System.out.println("Play Person...");4 }5

6 static voiddisplay(Person person){7 person.display();8 }9 }10

11 public class Husband extendsPerson{12 public static voidmain(String[] args) {13 Husband husband = newHusband();14 Person.display(husband); //向上转型

15 }16 }

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

谨慎继承

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

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

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

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

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

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/371675.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

delphi用TAdoStoredProc调用存储过程,兼容sql2005、2008、2014的远程事务问题

delphi7写的程序,在sql2000里没问题,调用sql2008、2014里的存储过程时,如果存储过程里操作了大量数据,很容易会莫名其妙的自己撤销掉,但是程序还识别不到,认为还在正常执行。今天尝试换了个控件&#xff1a…

8、SpringCloud高频面试题-版本1

1、SpringCloud组件有哪些 SpringCloud 是一系列框架的有序集合。它利用 SpringBoot 的开发便利性巧妙地简化了分布式系统基础设施的开发,如服务发现注册、配置中心、消息总线、负载均衡、断路器、数据监控等,都可以用 SpringBoot 的开发风格做到一键启…

JavaOne 2012:Java策略主题演讲和IBM主题演讲

与 JavaOne 2010 相似,我对JavaOne 2012的开始也很艰难。由于“计算机和打印机技术上的困难”,办理登机手续的人花了70分钟为我提供JavaOne徽章。 尽管我不是世界上最有耐心的人,但比等待更令人失望的是,我错过了参加“社区会议&a…

java citymap_Java实现Map集合二级联动

Map集合可以保存键值映射关系,这非常适合本实例所需要的数据结构,所有省份信息可以保存为Map集合的键,而每个键可以保存对应的城市信息,本实例就是利用Map集合实现了省市级联选择框,当选择省份信息时,将改变…

JavaOne 2012:使用HTML5和Java构建移动应用程序

我返回了Parc 55 (任务会议室),观看Max Katz的( Exadel开发人员关系)“用HTML5和Java构建移动应用程序” Bird-of-Feather(BoF)演示。 具体来说,Katz在Tiggzi (基于云的应…

HDU 2602.Bone Collector-动态规划0-1背包

Bone Collector Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 85530 Accepted Submission(s): 35381 Problem DescriptionMany years ago , in Teddy’s hometown there was a man who was called “Bone Col…

简单谈谈js中的MVC

MVC是什么? MVC是一种架构模式,它将应用抽象为3个部分:模型(数据)、视图、控制器(分发器)。 本文将用一个经典的例子todoList来展开(代码在最后)。 一个事件发生的过程&a…

BTrace:Java开发人员工具箱中的隐藏宝石

这篇文章是关于BTrace的 ,我正在考虑将其作为Java开发人员的隐藏宝藏。 BTrace是用于Java平台的安全,动态跟踪工具。 BTrace可用于动态跟踪正在运行的Java程序(类似于DTrace,适用于OpenSolaris应用程序和OS)。 不久&am…

Spring–添加SpringMVC –第2部分

在上一部分中,我们为经理和员工实现了控制器。 既然我们知道了解决方法,我们将做很少(但仅做很少)更复杂的事情–任务和时间表的控制器。 因此,让我们从org.timesheet.web开始。 TaskController 。 首先创建一个类&…

2016 Android Top 10 Library

过去的 2016 年,开源社区异常活跃,很多个人与公司争相开源自己的项目,让人眼花缭乱,然而有些项目只是昙花一现,有些项目却持久创造价值,为开发者提供了极大的便利,这些终究由时间来判断。今天&a…

您在eXo平台上的第一个Juzu Portlet

菊珠是佛教的佛珠。 一句话,我相信您已经学到了什么,印象深刻吗? 好的,我在这里不谈论佛教。 Juzu还是一个用于快速开发Portlet(以及即将推出的独立应用程序)的新框架。 您可以在Juzu网站上找到所需的所有…

Spring注入方式及注解配置

一:基于xml的DI(Dependency Injection) 注入类型: 定义学生Student实体类和小汽车Car实体类:进行封装和生成ToString(),并自定义属性Car Student 123456789101112131415161718192021222324252627282930313233343536373…

修改readonly属性的值

一般情况下,readonly属性的值是无法修改的,但可以通过特殊方式修改。定义一个student的类,其中name属性为readonly类型的变量 interface JFStudent : NSObjectproperty(nonatomic,copy,readonly) NSString *hisName;property(nonatomic,copy)…

ReactNative开发环境

此内容根据徐赢老师的文档整理后写处 原版地址:https://tuomaxu.gitbooks.io/reactnative/content/ ReactNative是跨平开发的解决方案,在开发平台的选择上,mac平台和win平台都可以。 所需要工具如下: 1,Nodejs环境 2&a…

MediaInfo源代码分析 1:整体结构

博客地址:http://blog.csdn.net/leixiaohua1020/article/details/12016231 MediaInfo源代码分析系列文章列表: MediaInfo源代码分析 1:整体结构MediaInfo源代码分析 2:API函数MediaInfo源代码分析 3:Open()函数MediaI…

射线碰撞检测

在我们的游戏开发过程中,有一个很重要的工作就是进行碰撞检测。例如在射击游戏中子弹是否击中敌人,在RPG游戏中是否捡到装备等等。在进行碰撞检测时,我们最常用的工具就是射线,Unity 3D的物理引擎也为我们提供了射线类以及相关的函…

php注册登录遍写入 遍验证,自动注册登录验证机制的php代码

在phpwind站点后台添加“广告管家”(CNZZ的一款广告投放的应用)的应用,整个“广告管家”通过iframe载入,载入的具体内容根据不同站点显示针对该站点的具体内容。出于意用性方面的考虑,需要以下二点:1、首次进入“广告管家”页面自…

Apache Wicket:记住我的功能

在Web应用程序中,具有“记住我”功能非常普遍,该功能使用户每次访问我们的网站时都能自动登录。 可以使用Spring Security来实现这种功能,但我认为将基于请求的身份验证框架与基于组件的Web框架结合使用并不是最好的主意。 这两个世界不能很好…

Ubuntu 安装中文

系统环境: 1. 官网 http://pinyin.sogou.com/linux/ 下载安装包。 2. 先运行 apt-get update 。 3. 再运行 apt-get -f install 。 4. 再运行 可能有的UBuntu系统自带了。 5. 如果下载的搜狐输入法安装包的格式为 .deb 的, 运行 : dpk…

JSF组件库–质量不只是零缺陷

自从我上次研究三个主要JSF组件库的质量以来,已经有一段时间了。 2009年12月,我开始比较RichFaces,Primefaces和ICEfaces的整体软件质量 。 从那时起,事情发生了变化,从现在开始,我想重新评估和更新它。 我…