text: 编程那些事儿：继承到底在面向对象编程里扮演什么样的角色呢
  前面我们对面向对象编程的抽象，封装两个特性进行了说明，我们知道抽象是我们认知世界的一个方式，而封装给了我们更加简洁方便的理解和处理我们抽象出来的实体类的手段。在完成了对实体类的抽象和封装之后，我们来看一下面向对象里体现相互关系中的一个重要概念：继承。
  继承在面向对象编程中为什么重要呢？首先它符合我们人类对于一类事物的认知思维，它表现的是抽象出来的类型之间的关系。或者说是它为我们的认知抽象过程提供了一种新方式。
  比如我们将真实世界中的人抽象为Person类来表示。继承的概念就是我们在进行新的抽象时，可以在已经抽象的基础上进行扩展来抽象新对象。
  为了表现这种关系，我们将现有的抽象称为超类型、超类、父类或基类。而新抽象出的类被称为子类型、子类、子类或派生类。
  如此我们通常说子类型是从超类型派生(或继承)的;超类型是子类型的泛化;子类型则是超类型的专门化。
  什么意思呢？超类拥有的内容，子类肯定都有，但是子类有的内容，超类不一定有。在泛化相当于总众多子类里找出来的共同特征，而专门化则是在共同内容的基础上进行增加的区别化内容，能够让类更加具体可区分。如此就形成了一种类的层级体系关系抽象。
  因为Java中不允许类的多重继承，所以每个类只能有一个超类，从而保证了所有类继承关系不会交叉。
  由此继承可用于在多个级别定义新的抽象。子类型可以被用作超类型定义另一个子类型，以此类推。继承便产生了一组按层次形式排列的类型。
  继承还有一个好处就是它能够让我们在不同层次结构的级别上使用不同程度的抽象。什么意思呢？就是可以创建出一个多层级的继承关系图谱，其中的每个类都是一个新抽象，由于子类会自动继承父类的内容，所以其各个类抽象的内容就发生了很大的变化。从而呈现出不同的类。
  比如，我们上面说的Person类，它位于继承层次结构的顶层。在企业业务体系中，顾客Customer是一个实体，是一个抽象目标，但是顾客同样是人，它也具备人的一切特征，所以我们在抽象顾客实体时，就不用再去重复抽象有关人的内容了，直接继承Person类即可。同样的企业员工也是具备人的特征，但又不同于一般的人，所以我们同样会通过继承Person类来进一步抽象定义员工Employee，如此依赖Customer和Employee的抽象结果就位于继承层次结构的第二层。
  而在企业中我们的雇员，我们可能有分为销售人员，管理人员，开发人员等，由此我们为了区分它们时需要进一步抽象出销售人员（Saler），管理人员（Manager），开发人员（Programmer）等更加专门化的类表示，这些的共同特征就是它们都是公司雇员，所以我们早抽象它们时就不用再去重复有关公司雇员的属性特征了，直接继承已经抽象出来的Employee类即可。
  在整个抽象层级体系中，当我们向上移动到继承级别时，我们将关注更重要的部分信息。换句话说，在更高的继承级别上，我们关注的是更大的图景，更加共同的内容；而在较低的继承级别上，我们会关注越来越多的细节。
  拿上面的例子来说，在Person级别，我们将重点放在Customer和Employee的共同特征上，而忽略了它们之间的差异。
  在Employee级别，我们关注的是Saler，Manager，Programmer的共同特征，而忽略了它们之间的差异。
  所以，在继承层次结构中，超类型及其子类型表示“is-a”关系。也就是说, Employee是一个Person; Saler是一个Employee，等等。
  因为较低层次的继承意味着更多更具体的信息，所以子类型总是包含它的父类型所拥有的信息，然后为了更加具体所以还要再此基础上定义更多。
  正是由于这种继承特性导致了面向对象编程中的另一个特性，就是我们常说的替代原则。
  什么意思呢？它说明了一种可替代性，谁替代谁呢？
  比如我们有这么一个场景，需要一个人Person，假设只需要知道这个人的姓名和性别即可，其它没什么要求，如此只需要是个人就可以，也就是说它具备人的基本特征姓名和性别信息即可，那么我们去找符合这个条件的，比如顾客Customer，因为它首先是个人，有姓名和性别信息，也就是说顾客首先是个人，然后才是一名顾客。同样的企业员工Employee，它首先也是个人，然后在企业中成为员工。
  所以，无论是顾客还是员工都可以满足前面需要人的姓名和性别信息的场景。完全可以请一位顾客去参与这个场景，或者派一名雇员去。
  如此就是说，Customer，Employee都能够去替换Person类。即子类可以替换它的超类型。
  因为Employee, Employee包含的名称和性别信息都是从Person中继承而来的。
  同时Employee可以包含更多的信息，如员工ID、雇佣日期、工资等。Customer可能还包含如账户，消费，余额等信息等。但这些当Employee和Customer去替换Person类时，它们只能表现为是一个Person，只需要name和gender信息即可。也就是说这种替代能够让原本的对象状态或者表现发生变化。
  如果某个上下文中我们想要一个Person，这意味着在该上下文中只有一个人的姓名和性别信息是与其相关的。
  也就是说在该上下文中，只要包含这两个信息的类都可以用，这也就意味着可以用Customer、Employee以及Saler、Manager或Programmer类替换Person，因为它们都是Person的子类型(直接或间接)，因为这些抽象都能提供该上下文需要的姓名和性别信息。
  另外由于子类型能够照单全收超类型定义的所有内容，所以这就为我们在编程级别上提供了另外一种机制，就是代码的重用机制。
  我们可以将那些通用的代码定义在超类型中，如此继承它的子类型就可以不用重复定义，而直接使用它们了。
  这就是超类型编写的代码可以被它的子类型重用。
  而对于子类型来说，通过继承不但简化了定义，还给自己提供了更大的主动性，它可以通过添加更多的功能或重新定义其超类型的已有功能来扩展其超类型的功能。
  其实继承也是用作实现面向对象编程的多态性的一种技术，因为继承允许我们编写多态代码。即代码是按照超类型编写的，但同样的代码它也适用于子类型。
  关于多态性，接下来我们会继续抽时间类具体说一下，因为它也是我们面向对象编程中一个非常重要的技术基础。