乐器与乐符的关系
package polymorphisn.music;
public enum Note {
MIDDLE_C, C_SHARP, B_FLAT;
}
/
package polymorphisn.music;
import static net.mindview.util.Print.*;
class Instrument{
public void play(Note n){
print("Instrument.play()");
}
}
public class Wind exends Instrument{
public void play(Note n){
System.out.println("Wind.play()"+n);
}
}
/
package polymorphisn.music;
public class Music {
public static void tune(Instrument i){
i.play(Note.MIDDLE_C);
}
public static void main(String[] args){
Wind flute = new Wind();
tune(flute);
}
}
//Output:
Wind.play() MIDDLE_C
Wind引用传递到tune()方法是合适的,因为Wind是从Instrument继承而来,Instrument的接口存在于Wind之中,是一个包含的关系。
多态的关键:让tune()方法实现多态;
(1)未用多态的方法来实现多个方法
package polymorphism.music;
import static net.mindview.util.print.*;
class Stringed extends Instrument{
public void play(Note n){
print("Stringed.play()"+n);
}
}
class Brass extends Instrument{
public void play(Note n){
print("Brass.play()"+n);
}
}
public class Music2{
public static void tune(Wind i){
i.play(Note.MIDDLE_C);
}
public static void tune(Stringed i){
i.play(Note.MIDDLE_C);
}
public static void tune(Brass i){
i.play(Note.MIDDLE_C);
}
public static void main(String[] args){
Wind flute = new Wind;
String violin = new Stringed();
Brass frencHorn = new Brass();
tune(flute);
tune(violin);
tune(frenchHorn);
}
}
///output:
Wind.play() MIDDLE_C
Stringed.play() MIDDLE_C
Bress.play() MIDDLE_C
(2)方法调用绑定
将一个方法调用同一个方法主题关联起来称作绑定1.前期绑定:在程序执行前绑定;2.后期绑定(动态绑定):运行时根据对象的类型进行绑定;JAVA中除了static和final之外,所有方法都是后期绑定的。因此可以断定所有的方法都是自动发生。
final 方法目的为防止别人覆盖该方法,且运行前绑定,关闭动态绑定,或许可以在某些情况下提高性能。
(3)向上转型继承
package polymorphism.shape;
public class Shape{
public void draw(){}
public void erase(){}
}
package polymorphism.shape;
import static net.mindview.util.Print.*;
public class Circle extends Shape{
public void draw(){print("Circle.draw()");}
public void erase(){print("Circle.erase()");}
}
package polymorphism.shape;
import static net.mindview.util.Print.*;
public class Square extends Shape {
public void draw(){print("Square.draw()");}
public void erase(){print("Square.erase()");}
}
package polymorphism.shape;
import static net.mindview.util.Print.*;
public class Triangle extends Shape{
public void draw(){print("Triangle.draw()");}
public void erase(){print("Triangle.erase()");}
}
package polymophism.shape;
import java.util.*;
public class RandomShapeGenerator{
private Random rand = new Random(47);
public Shape next(){
switch(rand.nextInt(3)){
default:
case 0: return new Circle();
case 1: return new Square();
case 2: return new Triangle();
}
}
}
import polymorphism.shape.*;
public class Shapes {
private static RandomShapeGenerator gen =
new RandomShapeGenerator();
public static void main(String[] args){
Shape[] s = new Shape[9];
for (int i=0;i<s.length;i++){
s[i]=gen.next();
}
for (Shape shp :s)
shp.draw();
}
}
///output
Triangle.draw()
Triangle.draw()
Square.draw()
Triangle.draw()
Square.draw()
Triangle.draw()
Square.draw()
Triangle.draw()
Circle.draw()
(4)“覆盖”私有方法
package polymorphism;
import static net.mindview.util.Print.*;
public class PrivateOverride{
private void f() {print("private f()");}
public static void main(String[] args){
PrivateOverride po = new Derived();
po.f();
}
}
class Derived extends PrivateOverride{
public void f(){print("public f()");}
}
//output
private f()
private 方法被自动认为是final的,无法覆盖。如果某个方法是静态的方法,他的行为就不具有多态性。即都会输出基类的方法;
(5)引用计数
import static net.mindview.util.Print.*;
class Shared{
private int refcount =0;
private static long counter =0;
private final long id =counter++;
public Shared(){
print("Creating"+this);
}
public void addRef(){refcount++;}
protected void dispose(){
if (--refcount ==0)
print("Disposing"+this);
}
public String toString(){return "Shared"+id;}
}
class Composing{
private Shared shared;
private static long counter =0;
private final long id = counter++;
public Composing(Shared shared){
print("Creating"+this);
this.shared=shared;
this.shared.addRef();
}
protected void dispose(){
print("disposing"+this);
shared.dispose();
}
public String toString(){return "Composing"+id;}
}
public class ReferenceCounting{
public static void main(String[] args){
Shared shared = new Shared();
Composing[] composing = {new Composing(shared),
new Composing(shared),new Composing(shared),
new Composing(shared),new Composing(shared)};
for (Composing c:composing)
c.dispose();
}
}
///output
Creating Shared 0
Creating Composing 0
Creating Composing 1
Creating Composing 2
Creating Composing 3
Creating Composing 4
disposing Composing 0
disposing Composing 1
disposing Composing 2
disposing Composing 3
disposing Composing 4
disposing Shared 0
(6)继承设计
继承在编译时需要知道确切的类型。
import static net.mindview.util.Print.*;
class Actor {
public void act(){}
}
class HappyActor extends Actor{
public void act(){print(HappyActor);}
}
class SadActor extends Actor {
public void act(){print("SadActor");}
}
class Stage {
private Actor actor = new HappyActor();
public void change(){actor = new SadActor();}
public void performPlay(){actor.act();}
}
public class Transmogrify{
public static void main(String[] args){
Stage stage = new Stage();
stage.performPlay();
stage.change();
stage.performPlay();
}
}
///output
HappyActor
SadActor
(7)纯继承与扩展
在基类中已有的方法才可以在导出类中被覆盖。
优点:基类可以接收发送给导出类的任何消息,因为二者有着完全相同的接口;
缺点:导出类中接口的扩展部分不能被基类访问,向上转型,无法调用这些新方法。
解决方案:向下转型,运行态的类型识别。