1.6继承

本贴最后更新于 3373 天前,其中的信息可能已经时移世易

   对象这种观念,本身就是十分方便的工具,使得你可以通过概念将数据和功能封装到一起,因此可以对问题空间的观念给出恰当的表示,而不用受制于必须使用底层机器语言。这些概念都是使用关键字class来表示,它们形成了编程语言中的基本单位。

    遗憾的是,这样做还是有很多麻烦:在创建一个类后,即使另一个新类与其具有相似的功能,你还是得创建一个新类。如果我们能够以现有的类为基础,复制它,然后通过添加和修改这个副本来创建新来那就要好的多了。通过继承便可以达到这样的效果,不过也有例外,当源类(被称为基类、超类或父类)发生变动时,被修改的“副本”(被称为导出类、继承类或子类)也会反映出这些变动(如下图所示,这张UML图中的箭头从导出类指向基类,就像稍后你会看到的,通常存在一个以上的导出类)。

继承图零

    类型不仅仅只是描述了作用于一个对象集合上的约束条件,同时还有与其他类型之间的关系。两个类型可以有相同的特性或行为,但是其中一个类型可能比另一个含有更多的特性,并且可以处理更多的消息(或以不同的方式来处理消息)。继承使用基类性和导出类型的概念表示了这种类型之间的相似性。一个基类型包含其所有的导出类型所共享的特性和行为。所以可以创建一个基类型来表示系统中某些对象的核心概念,从基类型中导出其他类型,来表示此核心可以被实现的各种的不同的方式。

    以垃圾回收机制为例,它用来归类散落的垃圾。“垃圾”是基类型,每件垃圾都有自己的重量、价值等特性,可以被切碎、融化或分解。在此基础上,可以通过添加额外的特性(例如瓶子有颜色)或行为(铝罐可以被压碎,铁罐可以被磁化)导出更具体的垃圾类型。此外,某些行为可能不同(例如纸的价值取决于其类型和状态)。可以通过使用继承来构建一个类型层次结构,以此来表示待求解的某种类型的问题。

    第二个例子是经典的几何形的例子,在这计算机辅助设计系统或游戏仿真系统中可能被用到。基类是几何形,每个几何形都有尺寸、颜色、位置等,同时每一个几何形都可以被绘制、擦除、移动和着色等。在此基础上,可以导出(继承出)具体的几何形状——圆形、正方形、三角形等——每一种都具有额外的特性和行为,例如某些形状可以被翻转。某些行为可能并不相同,例如计算几何形状的面积。类型层次结构同时体现了几何形状之间的相似性和差异性(如下图所示)。

继承图二

    以同样的术语将解决方案转换成问题是大有裨益的,因为不需要在问题描述和解决方案描述之间建立过多的中间模型。通过使用对象,类型层次结构成了主要模型,因此,可以直接从真实世界中对系统的描述过渡到用代码对系统进行描述。事实上,对使用面向对象涉及的人们来说,困难之一是从开始到结束过于简单。对于训练有素、善于寻找复杂的解决方案的头脑来说,可能会在一开始就被这种简单性难倒。

    当继承现有类型是,也就创造了新的类型。这个新的类型不仅包括现有类型的成员(尽管private成员被隐藏了起来,并且不可访问),而且更重要的是他复制了基类的接口。也就是说,所有可以发送给基类对象的消息同时也可以发送给导出类对象。由于通过发送给类的消息的类型可知类的类型,所以这也就意味着导出类与基类具有相同的类型。在前面的例子中,“一个圆形也就是一个几何形”。通过继承而产生的类型等价性是理解面向对象程序设计方法内涵的重要门槛。

    由于基类和导出类具有相同的基础接口,所以伴随此接口的必定有某些具体的实现。也就是说,当对象接收到特定消息的时候,必须有某些代码去执行。如果只是简单地继承一个类而并不做其他任何事,那么在基类接口中的方法会直接继承到导出类中。这意味着导出类的对象不仅与基类拥有相同的类型,而且还拥有相同的行为,这样做没有什么特别意义。

    有两种方法可以是积累与导出类产生差异。第一种方法非常直接:直接在导出类中添加方法。这些新方法并不是基类接口的一部分。这意味着基类不能直接满足你的所有需求,因此必须添加更多的方法。这种对继承简单而基本的使用方式,有事对解决问题来说确实是一种完美的解决方式。但是,应该仔细考虑是否存在基类也需要这些额外方法的可用性。这种设计的发现与迭代过程在面向对象程序设计中经常发生。(如下图所示)。

继承图二

    虽然继承有时可能意味着在接口中添加新方法(尤其是在以extends关键字表示继承的Java中),但并非总需如此。第二种也是更重要的y8zhong是导出类和基类之间产生差异的地方就是改变现有基类的方法和行为,这被称之为覆盖(overriding)那个方法(如下图所示)

继承图三

    想要覆盖某个方法,可以直接在导出类中创建该方法的新定义即可。你可以说:“此时,我正在使用相同的接口方法,但是我想在新的类型中做些不同的事情”。

    1.6.1 ”是一个“与“像是一个”关系

    对于继承可能会引发某些争论:继承应该只是覆盖基类的方法(而不添加在基类中没有的新方法)吗?如果这样做,就意味着导出类和积累是完全相同的类型,因为他们具有完全相同的借口。结果可以用一个导出类对象来完全替代一个基类对象。这可以被视为纯粹替代,通常称之为替代原则。在某种意义上,这是一种处理继承的理想方式。我们经常将这些情况下的基类与导出类之间的关系成为“is-a(是一个)关系,因为可以说“一个圆形就是一个几何形状”。判断是否继承就是要确定是否可以用“is-a”来描述类之间的关系,并使之具有实际意义。

    有时必须在导出类型中添加新的借口元素,这样也就扩展了接口。这个新的类型仍然可以替代基类,但是这种替代并不完美,因为基类无法访问导出类中新添加的方法。这种情况我们可以描述为 is-like-a(像一个)关系。新类型具有旧类型的接口,但是它还包含其他方法,所以不能说它们完全相同。以空调为例,假设房子里已经布线安装好了所有的冷气设备的控制器,也就是说,房子具备了让你控制冷气设备的接口。想象一下,如果空调坏了,你用一个既能制冷又能制热的热力泵替换了它,那么这个热力泵就is-like-a空调,但是它可以做更多的事。因为房子的控制系统被设计为只能控制冷气设备,所以他只能和新对象中的制冷部分进行通信。尽管新对象的接口已经被扩展了,但是现在的接口除了原来的接口之外,其他的东西一无所知。

    当然,在看过这个设计之后,很显然会发现,制冷系统这个基类不够一般化,应该将其更名为“温度控制系统”,使其可以包括制热功能,这样我们就可以陶俑替代原则了。这张图说明了在真实世界中进行设计师很可能会发生的事情。

    当你看到替代原则时很容易会认为这种方式(纯粹替代)是唯一可行的方式,而且事实上,用这种方式设计是很好的。但是你会时常发现,同样显然的是你必须在导出类的忌口中添加新方法。只要仔细审视,两种方法的适用场合应该是相当明显的。

相关帖子

2 回帖

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...

推荐标签 标签

  • 又拍云

    又拍云是国内领先的 CDN 服务提供商,国家工信部认证通过的“可信云”,乌云众测平台认证的“安全云”,为移动时代的创业者提供新一代的 CDN 加速服务。

    21 引用 • 37 回帖 • 545 关注
  • Pipe

    Pipe 是一款小而美的开源博客平台。Pipe 有着非常活跃的社区,可将文章作为帖子推送到社区,来自社区的回帖将作为博客评论进行联动(具体细节请浏览 B3log 构思 - 分布式社区网络)。

    这是一种全新的网络社区体验,让热爱记录和分享的你不再感到孤单!

    132 引用 • 1114 回帖 • 124 关注
  • Electron

    Electron 基于 Chromium 和 Node.js,让你可以使用 HTML、CSS 和 JavaScript 构建应用。它是一个由 GitHub 及众多贡献者组成的活跃社区共同维护的开源项目,兼容 Mac、Windows 和 Linux,它构建的应用可在这三个操作系统上面运行。

    15 引用 • 136 回帖
  • WordPress

    WordPress 是一个使用 PHP 语言开发的博客平台,用户可以在支持 PHP 和 MySQL 数据库的服务器上架设自己的博客。也可以把 WordPress 当作一个内容管理系统(CMS)来使用。WordPress 是一个免费的开源项目,在 GNU 通用公共许可证(GPLv2)下授权发布。

    66 引用 • 114 回帖 • 228 关注
  • Node.js

    Node.js 是一个基于 Chrome JavaScript 运行时建立的平台, 用于方便地搭建响应速度快、易于扩展的网络应用。Node.js 使用事件驱动, 非阻塞 I/O 模型而得以轻量和高效。

    139 引用 • 269 回帖 • 43 关注
  • Bootstrap

    Bootstrap 是 Twitter 推出的一个用于前端开发的开源工具包。它由 Twitter 的设计师 Mark Otto 和 Jacob Thornton 合作开发,是一个 CSS / HTML 框架。

    18 引用 • 33 回帖 • 660 关注
  • Vim

    Vim 是类 UNIX 系统文本编辑器 Vi 的加强版本,加入了更多特性来帮助编辑源代码。Vim 的部分增强功能包括文件比较(vimdiff)、语法高亮、全面的帮助系统、本地脚本(Vimscript)和便于选择的可视化模式。

    29 引用 • 66 回帖
  • Gitea

    Gitea 是一个开源社区驱动的轻量级代码托管解决方案,后端采用 Go 编写,采用 MIT 许可证。

    4 引用 • 16 回帖 • 6 关注
  • Mobi.css

    Mobi.css is a lightweight, flexible CSS framework that focus on mobile.

    1 引用 • 6 回帖 • 733 关注
  • ReactiveX

    ReactiveX 是一个专注于异步编程与控制可观察数据(或者事件)流的 API。它组合了观察者模式,迭代器模式和函数式编程的优秀思想。

    1 引用 • 2 回帖 • 155 关注
  • 安全

    安全永远都不是一个小问题。

    199 引用 • 816 回帖 • 2 关注
  • 机器学习

    机器学习(Machine Learning)是一门多领域交叉学科,涉及概率论、统计学、逼近论、凸分析、算法复杂度理论等多门学科。专门研究计算机怎样模拟或实现人类的学习行为,以获取新的知识或技能,重新组织已有的知识结构使之不断改善自身的性能。

    83 引用 • 37 回帖
  • Kafka

    Kafka 是一种高吞吐量的分布式发布订阅消息系统,它可以处理消费者规模的网站中的所有动作流数据。 这种动作(网页浏览,搜索和其他用户的行动)是现代系统中许多功能的基础。 这些数据通常是由于吞吐量的要求而通过处理日志和日志聚合来解决。

    36 引用 • 35 回帖
  • API

    应用程序编程接口(Application Programming Interface)是一些预先定义的函数,目的是提供应用程序与开发人员基于某软件或硬件得以访问一组例程的能力,而又无需访问源码,或理解内部工作机制的细节。

    77 引用 • 430 回帖
  • 生活

    生活是指人类生存过程中的各项活动的总和,范畴较广,一般指为幸福的意义而存在。生活实际上是对人生的一种诠释。生活包括人类在社会中与自己息息相关的日常活动和心理影射。

    230 引用 • 1454 回帖
  • SMTP

    SMTP(Simple Mail Transfer Protocol)即简单邮件传输协议,它是一组用于由源地址到目的地址传送邮件的规则,由它来控制信件的中转方式。SMTP 协议属于 TCP/IP 协议簇,它帮助每台计算机在发送或中转信件时找到下一个目的地。

    4 引用 • 18 回帖 • 614 关注
  • Kotlin

    Kotlin 是一种在 Java 虚拟机上运行的静态类型编程语言,由 JetBrains 设计开发并开源。Kotlin 可以编译成 Java 字节码,也可以编译成 JavaScript,方便在没有 JVM 的设备上运行。在 Google I/O 2017 中,Google 宣布 Kotlin 成为 Android 官方开发语言。

    19 引用 • 33 回帖 • 63 关注
  • 域名

    域名(Domain Name),简称域名、网域,是由一串用点分隔的名字组成的 Internet 上某一台计算机或计算机组的名称,用于在数据传输时标识计算机的电子方位(有时也指地理位置)。

    43 引用 • 208 回帖
  • 京东

    京东是中国最大的自营式电商企业,2015 年第一季度在中国自营式 B2C 电商市场的占有率为 56.3%。2014 年 5 月,京东在美国纳斯达克证券交易所正式挂牌上市(股票代码:JD),是中国第一个成功赴美上市的大型综合型电商平台,与腾讯、百度等中国互联网巨头共同跻身全球前十大互联网公司排行榜。

    14 引用 • 102 回帖 • 374 关注
  • 反馈

    Communication channel for makers and users.

    123 引用 • 911 回帖 • 245 关注
  • Hibernate

    Hibernate 是一个开放源代码的对象关系映射框架,它对 JDBC 进行了非常轻量级的对象封装,使得 Java 程序员可以随心所欲的使用对象编程思维来操纵数据库。

    39 引用 • 103 回帖 • 710 关注
  • 思源笔记

    思源笔记是一款隐私优先的个人知识管理系统,支持完全离线使用,同时也支持端到端加密同步。

    融合块、大纲和双向链接,重构你的思维。

    22352 引用 • 89437 回帖
  • JetBrains

    JetBrains 是一家捷克的软件开发公司,该公司位于捷克的布拉格,并在俄国的圣彼得堡及美国麻州波士顿都设有办公室,该公司最为人所熟知的产品是 Java 编程语言开发撰写时所用的集成开发环境:IntelliJ IDEA

    18 引用 • 54 回帖
  • Elasticsearch

    Elasticsearch 是一个基于 Lucene 的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎,基于 RESTful 接口。Elasticsearch 是用 Java 开发的,并作为 Apache 许可条款下的开放源码发布,是当前流行的企业级搜索引擎。设计用于云计算中,能够达到实时搜索,稳定,可靠,快速,安装使用方便。

    117 引用 • 99 回帖 • 212 关注
  • Log4j

    Log4j 是 Apache 开源的一款使用广泛的 Java 日志组件。

    20 引用 • 18 回帖 • 30 关注
  • GitBook

    GitBook 使您的团队可以轻松编写和维护高质量的文档。 分享知识,提高团队的工作效率,让用户满意。

    3 引用 • 8 回帖 • 4 关注
  • 链滴

    链滴是一个记录生活的地方。

    记录生活,连接点滴

    153 引用 • 3783 回帖 • 1 关注