多态(1)——向上转型和忘记对象类型

多态通过分离做什么和怎么做,将接口与实现分离开来,改善了代码的结构和可读性,还能创建可扩展的程序——即在创建的时候和添加新功能的时候都可以“生长”的程序。

封装是指,一种将抽象性函数接口的实现细节部分包装、隐藏起来的方法。同时,它也是一种防止外界调用端,去访问对象内部实现细节的手段。

多态的作用则是消除这些类型之间的耦合关系。

 

继承允许将对象视为它自己本身的类型或基类型进行处理,一份代码可以无差别运行在不同类型上。

多态则是允许一种类型表现出与其他类型之间的区别,这些区别是通过方法行为不同表现出来的,这些方法都可以通过同一基类的调用。

 

一、向上转型

对某个对象的引用视为其基类型成为向上转型

看下面有关乐器的例子:

1 //新建enum的枚举类
2 public enum Note {
3     MIDDLE_C,C_SHARP,D_FLAT;
4 }
 1 class Instrument{
 2     public void play(Note n) {
 3         System.out.println("Instrment.play()");
 4     }
 5 }
 6 class Wind extends Instrument{
 7     public void play(Note n) {
 8         System.out.println("wind.play()" + n);
 9     }
10 }
11 public class Music {
12     public static void tune(Instrument i) {
13         i.play(Note.MIDDLE_C);
14     }
15     public static void main(String[] args) {
16         Wind flute = new Wind();
17         tune(flute);
18     }
19 }

运行结果:

wind.play()MIDDLE_C

 

可以看出,Music.tune()接受了Instrument的引用,同时,接受Instrument导出的Wind类,当Wind的引用传递到tune()方法时,不需要任何的转换,所以,Instrument的接口存在于Wind中。

二、忘记对象类型

 

 1 class Instrument{
 2     public void play(Note n) {
 3         System.out.println("Instrment.play()");
 4     }
 5 }
 6 class Wind extends Instrument{
 7     public void play(Note n) {
 8         System.out.println("Wind.play()" + n);
 9     }
10 }
11 class Stringed extends Instrument{
12     public void play(Note n) {
13         System.out.println("Stringed.play()" + n);
14     }
15 }
16 class Brass extends Instrument{
17     public void play(Note n) {
18         System.out.println("Brass.play()" + n);
19     }
20 }
21 public class Music {
22     public static void tune(Instrument i) {
23         i.play(Note.MIDDLE_C);
24     }
25     public static void tune(Wind i) {
26         i.play(Note.MIDDLE_C);
27     }
28     public static void tune(Stringed i) {
29         i.play(Note.MIDDLE_C);
30     }
31     public static void tune(Brass i) {
32         i.play(Note.MIDDLE_C);
33     }
34     public static void main(String[] args) {
35         Wind flute = new Wind();
36         Stringed violin = new Stringed();
37         Brass frenchHorn = new Brass();
38         tune(flute);
39         tune(violin);
40         tune(frenchHorn);
41     }
42 }

运行结果:

Wind.play()MIDDLE_C

Stringed.play()MIDDLE_C

Brass.play()MIDDLE_C

 

这样,是无法看到Wind,Stringed,Brass类型的基类Instrument

这样做是可以的,但必须对每一个特定的新类型写特定的tune()方法,这将造成极大的工作量,而且如果忘记重载某个方法,编译器不会返回错误信息,整个类型变得难以操纵。

posted @ 2018-09-05 20:20  dafeifeifei  阅读(61)  评论(0)    收藏  举报