多态是面向对象的编程语言中非常重要的一种特性,通过分离做什么和怎样做,可以把接口和实现分离开来。多态是通过向上转型实现的,而即使向上转型了还仍然可以正确调用子类的方法,这就是动态绑定,又叫后期绑定这种特性实现的。
下面,我分别举普通类,接口,内部类来说明多态。
普通类:
class Instrument {
void play(Note n) { print("Instrument.play() " + n); }
String what() { return "Instrument"; }
void adjust() { print("Adjusting Instrument"); }
}
class Wind extends Instrument {
void play(Note n) { print("Wind.play() " + n); }
String what() { return "Wind"; }
void adjust() { print("Adjusting Wind"); }
}
class Percussion extends Instrument {
void play(Note n) { print("Percussion.play() " + n); }
String what() { return "Percussion"; }
void adjust() { print("Adjusting Percussion"); }
}
public class Music3 {
public static void tune(Instrument i) {
i.play(Note.MIDDLE_C);
}
public static void main(String[] args) {
Instrument[] orchestra = {
new Wind(),
new Percussion()
};
for(Instrument i:orchestra)
tune(i);
}
} /* Output:
Wind.play() MIDDLE_C
Percussion.play() MIDDLE_C
这个例子可就体现出了多态的好处,可以后期添加新的类,进行扩展,而无需修改已有的调用方法,这就把需要改变的和不变的分开了,这就是多态的好处。
接口和抽象类:
接口和抽象类为多态提供了一种更加结构化的方法。接口和抽象类的区别,就是抽象类并不是纯接口,它可以实现方法。我就举个接口的例子吧。
interface Instrument {
void play(Note n); // Automatically public
void adjust();
}
class Wind implements Instrument {
public void play(Note n) {
print(this + ".play() " + n);
}
public String toString() { return "Wind"; }
public void adjust() { print(this + ".adjust()"); }
}
class Percussion implements Instrument {
public void play(Note n) {
print(this + ".play() " + n);
}
public String toString() { return "Percussion"; }
public void adjust() { print(this + ".adjust()"); }
}
class Brass extends Wind {
public String toString() { return "Brass"; }
}
class Woodwind extends Wind {
public String toString() { return "Woodwind"; }
}
public class Music5 {
static void tune(Instrument i) {
i.play(Note.MIDDLE_C);
}
static void tuneAll(Instrument[] e) {
for(Instrument i : e)
tune(i);
}
public static void main(String[] args) {
// Upcasting during addition to the array:
Instrument[] orchestra = {
new Wind(),
new Percussion(),
new Brass(),
new Woodwind()
};
tuneAll(orchestra);
}
} /* Output:
Wind.play() MIDDLE_C
Percussion.play() MIDDLE_C
Stringed.play() MIDDLE_C
Brass.play() MIDDLE_C
Woodwind.play() MIDDLE_C
这个例子就看出接口的好处了,要调用这个方法,只要实现了这个接口即可,而如果用普通的类则必须继承,可见还是实现接口比比较方便。
这里还涉及到一种设计方式,可以完全解耦合,这个将放在设计模式里面讲。通过这种设计模式,你就会知道通过接口可以完全解耦合。
内部类:
内部类重要的特性且我们平常能过用到的就是,能够实现多重继承,你也许会说接口也能实现多重继承,但如果要继承的是2个类呢,那恐怕不行了吧,可内部类就可以。
当用内部类实现了多重继承时,你就可以多态地转换为多种类型了。看代码:
interface A {}
interface B {}
class X implements A, B {}
class Y implements A {
B makeB() {
// Anonymous inner class:
return new B() {};
}
}
public class MultiInterfaces {
static void takesA(A a) {}
static void takesB(B b) {}
public static void main(String[] args) {
X x = new X();
Y y = new Y();
takesA(x);
takesA(y);
takesB(x);
takesB(y.makeB());
}
}
看这就是内部类的强大,当然如果你不需要多重继承的话,当然可以用到其它代码来实现。
总结:接口和内部类结合起来,就可以解决C++中多重继承所能解决的问题,而且容易理解的多。
多态机制,其实是设计阶段考虑的问题,到底该用什么样的设计方式,用接口还是内部类的,得看实际情况,随着编程经验的增加,到底用什么样的实现方式会有更深的理解。
欢迎评论,欢迎讨论。