🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
## [向上转型](https://lingcoder.gitee.io/onjava8/#/book/08-Reuse?id=%e5%90%91%e4%b8%8a%e8%bd%ac%e5%9e%8b) 继承最重要的方面不是为新类提供方法。它是新类与基类的一种关系。简而言之,这种关系可以表述为“新类是已有类的一种类型”。 这种描述并非是解释继承的一种花哨方式,这是直接由语言支持的。例如,假设有一个基类**Instrument**代表音乐乐器和一个派生类**Wind**。 因为继承保证了基类的所有方法在派生类中也是可用的,所以任意发送给该基类的消息也能发送给派生类。如果**Instrument**有一个`play()`方法,那么**Wind**也有该方法。这意味着你可以准确地说**Wind**对象也是一种类型的**Instrument**。下面例子展示了编译器是如何支持这一概念的: ~~~ // reuse/Wind.java // Inheritance & upcasting class Instrument { public void play() {} static void tune(Instrument i) { // ... i.play(); } } // Wind objects are instruments // because they have the same interface: public class Wind extends Instrument { public static void main(String[] args) { Wind flute = new Wind(); Instrument.tune(flute); // Upcasting } } ~~~ `tune()`方法接受了一个**Instrument**类型的引用。但是,在**Wind**的`main()`方法里,`tune()`方法却传入了一个**Wind**引用。鉴于 Java 对类型检查十分严格,一个接收一种类型的方法接受了另一种类型看起来很奇怪,除非你意识到**Wind**对象同时也是一个**Instrument**对象,而且**Instrument**的`tune`方法一定会存在于**Wind**中。在`tune()`中,代码对**Instrument**和 所有**Instrument**的派生类起作用,这种把**Wind**引用转换为**Instrument**引用的行为称作*向上转型*。 该术语是基于传统的类继承图:图最上面是根,然后向下铺展。(当然你可以以任意方式画你认为有帮助的类图。)于是,**Wind.java**的类图是: ![Wind 类图](https://lingcoder.gitee.io/onjava8/images/1561774164644.png) 继承图中派生类转型为基类是向上的,所以通常称作*向上转型*。因为是从一个更具体的类转化为一个更一般的类,所以向上转型永远是安全的。也就是说,派生类是基类的一个超集。它可能比基类包含更多的方法,但它必须至少具有与基类一样的方法。在向上转型期间,类接口只可能失去方法,不会增加方法。这就是为什么编译器在没有任何明确转型或其他特殊标记的情况下,仍然允许向上转型的原因。 也可以执行与向上转型相反的向下转型,但是会有问题,对于该问题会放在下一章和“类型信息”一章进行更深入的探讨。