1.6继承

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

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

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

继承图零

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

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

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

继承图二

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

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

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

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

继承图二

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

继承图三

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

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

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

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

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

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

相关帖子

2 回帖

欢迎来到这里!

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

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

推荐标签 标签

  • 百度

    百度(Nasdaq:BIDU)是全球最大的中文搜索引擎、最大的中文网站。2000 年 1 月由李彦宏创立于北京中关村,致力于向人们提供“简单,可依赖”的信息获取方式。“百度”二字源于中国宋朝词人辛弃疾的《青玉案·元夕》词句“众里寻他千百度”,象征着百度对中文信息检索技术的执著追求。

    63 引用 • 785 回帖 • 112 关注
  • IBM

    IBM(国际商业机器公司)或万国商业机器公司,简称 IBM(International Business Machines Corporation),总公司在纽约州阿蒙克市。1911 年托马斯·沃森创立于美国,是全球最大的信息技术和业务解决方案公司,拥有全球雇员 30 多万人,业务遍及 160 多个国家和地区。

    17 引用 • 53 回帖 • 146 关注
  • 服务器

    服务器,也称伺服器,是提供计算服务的设备。由于服务器需要响应服务请求,并进行处理,因此一般来说服务器应具备承担服务并且保障服务的能力。

    125 引用 • 585 回帖
  • 机器学习

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

    83 引用 • 37 回帖
  • frp

    frp 是一个可用于内网穿透的高性能的反向代理应用,支持 TCP、UDP、 HTTP 和 HTTPS 协议。

    20 引用 • 7 回帖
  • JRebel

    JRebel 是一款 Java 虚拟机插件,它使得 Java 程序员能在不进行重部署的情况下,即时看到代码的改变对一个应用程序带来的影响。

    26 引用 • 78 回帖 • 676 关注
  • 爬虫

    网络爬虫(Spider、Crawler),是一种按照一定的规则,自动地抓取万维网信息的程序。

    106 引用 • 275 回帖
  • Swift

    Swift 是苹果于 2014 年 WWDC(苹果开发者大会)发布的开发语言,可与 Objective-C 共同运行于 Mac OS 和 iOS 平台,用于搭建基于苹果平台的应用程序。

    36 引用 • 37 回帖 • 545 关注
  • 强迫症

    强迫症(OCD)属于焦虑障碍的一种类型,是一组以强迫思维和强迫行为为主要临床表现的神经精神疾病,其特点为有意识的强迫和反强迫并存,一些毫无意义、甚至违背自己意愿的想法或冲动反反复复侵入患者的日常生活。

    15 引用 • 161 回帖
  • Sillot

    Insights(注意当前设置 master 为默认分支)

    汐洛彖夲肜矩阵(Sillot T☳Converbenk Matrix),致力于服务智慧新彖乄,具有彖乄驱动、极致优雅、开发者友好的特点。其中汐洛绞架(Sillot-Gibbet)基于自思源笔记(siyuan-note),前身是思源笔记汐洛版(更早是思源笔记汐洛分支),是智慧新录乄终端(多端融合,移动端优先)。

    主仓库地址:Hi-Windom/Sillot

    文档地址:sillot.db.sc.cn

    注意事项:

    1. ⚠️ 汐洛仍在早期开发阶段,尚不稳定
    2. ⚠️ 汐洛并非面向普通用户设计,使用前请了解风险
    3. ⚠️ 汐洛绞架基于思源笔记,开发者尽最大努力与思源笔记保持兼容,但无法实现 100% 兼容
    29 引用 • 25 回帖 • 105 关注
  • V2Ray
    1 引用 • 15 回帖
  • OkHttp

    OkHttp 是一款 HTTP & HTTP/2 客户端库,专为 Android 和 Java 应用打造。

    16 引用 • 6 回帖 • 84 关注
  • 互联网

    互联网(Internet),又称网际网络,或音译因特网、英特网。互联网始于 1969 年美国的阿帕网,是网络与网络之间所串连成的庞大网络,这些网络以一组通用的协议相连,形成逻辑上的单一巨大国际网络。

    99 引用 • 367 回帖
  • PWA

    PWA(Progressive Web App)是 Google 在 2015 年提出、2016 年 6 月开始推广的项目。它结合了一系列现代 Web 技术,在网页应用中实现和原生应用相近的用户体验。

    14 引用 • 69 回帖 • 176 关注
  • Kubernetes

    Kubernetes 是 Google 开源的一个容器编排引擎,它支持自动化部署、大规模可伸缩、应用容器化管理。

    116 引用 • 54 回帖 • 5 关注
  • LeetCode

    LeetCode(力扣)是一个全球极客挚爱的高质量技术成长平台,想要学习和提升专业能力从这里开始,充足技术干货等你来啃,轻松拿下 Dream Offer!

    209 引用 • 72 回帖
  • Elasticsearch

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

    117 引用 • 99 回帖 • 204 关注
  • Laravel

    Laravel 是一套简洁、优雅的 PHP Web 开发框架。它采用 MVC 设计,是一款崇尚开发效率的全栈框架。

    20 引用 • 23 回帖 • 737 关注
  • 音乐

    你听到信仰的声音了么?

    61 引用 • 512 回帖
  • Solidity

    Solidity 是一种智能合约高级语言,运行在 [以太坊] 虚拟机(EVM)之上。它的语法接近于 JavaScript,是一种面向对象的语言。

    3 引用 • 18 回帖 • 431 关注
  • PWL

    组织简介

    用爱发电 (Programming With Love) 是一个以开源精神为核心的民间开源爱好者技术组织,“用爱发电”象征开源与贡献精神,加入组织,代表你将遵守组织的“个人开源爱好者”的各项条款。申请加入:用爱发电组织邀请帖
    用爱发电组织官网:https://programmingwithlove.stackoverflow.wiki/

    用爱发电组织的核心驱动力:

    • 遵守开源守则,体现开源&贡献精神:以分享为目的,拒绝非法牟利。
    • 自我保护:使用适当的 License 保护自己的原创作品。
    • 尊重他人:不以各种理由、各种漏洞进行未经允许的抄袭、散播、洩露;以礼相待,尊重所有对社区做出贡献的开发者;通过他人的分享习得知识,要留下足迹,表示感谢。
    • 热爱编程、热爱学习:加入组织,热爱编程是首当其要的。我们欢迎热爱讨论、分享、提问的朋友,也同样欢迎默默成就的朋友。
    • 倾听:正确并恳切对待、处理问题与建议,及时修复开源项目的 Bug ,及时与反馈者沟通。不抬杠、不无视、不辱骂。
    • 平视:不诋毁、轻视、嘲讽其他开发者,主动提出建议、施以帮助,以和谐为本。只要他人肯努力,你也可能会被昔日小看的人所超越,所以请保持谦虚。
    • 乐观且活跃:你的努力决定了你的高度。不要放弃,多年后回头俯瞰,才会发现自己已经成就往日所仰望的水平。积极地将项目开源,帮助他人学习、改进,自己也会获得相应的提升、成就与成就感。
    1 引用 • 487 回帖 • 2 关注
  • 阿里巴巴

    阿里巴巴网络技术有限公司(简称:阿里巴巴集团)是以曾担任英语教师的马云为首的 18 人,于 1999 年在中国杭州创立,他们相信互联网能够创造公平的竞争环境,让小企业通过创新与科技扩展业务,并在参与国内或全球市场竞争时处于更有利的位置。

    43 引用 • 221 回帖 • 75 关注
  • GitBook

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

    3 引用 • 8 回帖 • 1 关注
  • DevOps

    DevOps(Development 和 Operations 的组合词)是一组过程、方法与系统的统称,用于促进开发(应用程序/软件工程)、技术运营和质量保障(QA)部门之间的沟通、协作与整合。

    57 引用 • 25 回帖 • 7 关注
  • GitHub

    GitHub 于 2008 年上线,目前,除了 Git 代码仓库托管及基本的 Web 管理界面以外,还提供了订阅、讨论组、文本渲染、在线文件编辑器、协作图谱(报表)、代码片段分享(Gist)等功能。正因为这些功能所提供的便利,又经过长期的积累,GitHub 的用户活跃度很高,在开源世界里享有深远的声望,并形成了社交化编程文化(Social Coding)。

    210 引用 • 2040 回帖
  • Vue.js

    Vue.js(读音 /vju ː/,类似于 view)是一个构建数据驱动的 Web 界面库。Vue.js 的目标是通过尽可能简单的 API 实现响应的数据绑定和组合的视图组件。

    267 引用 • 666 回帖
  • TextBundle

    TextBundle 文件格式旨在应用程序之间交换 Markdown 或 Fountain 之类的纯文本文件时,提供更无缝的用户体验。

    1 引用 • 2 回帖 • 76 关注