《JAVA编程思想》学习备忘(第277页Polymorphism-1)

Polymorphism

多态

Upcasting revisited

 示例:

public enum Note {
    MIDDLE_C, C_SHARP, B_FLAT;
}

class Instrument {
 public void play(Note n){
  System.out.println("Instrument.play()");
 }
}

public class Wind extends Instrument {
 public void play(Note n){
  System.out.println("Wind.play() "+n);
 }
}

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);
 }
}

输出:

Wind.play() MIDDLE_C

tune方法形参为Instrument,在main方法中传递了一个Wind参数,不需要强转。只要是继承于Instrument的类的实例,都可这样传递。

 

Forgetting the object type

你需要为父类的不同子类各写一个新的方法,以接收不同的参数。

示例:

public class Stringed extends Instrument {
    public void play(Note n){
     System.out.println("Stringed.play() " + n);
    }
}

public class Brass extends Instrument {
 public void play(Note n){
  System.out.println("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();
  Stringed violin = new Stringed();
  Brass frenchHorn = new Brass();
  tune(flute);
  tune(violin);
  tune(frenchHorn);
 }
}

输出:

Wind.play() MIDDLE_C
Stringed.play() MIDDLE_C
Brass.play() MIDDLE_C

 

The twist

Method-call binding

Connecting a method call to a method body is called binding.

...The solution is called late binding,which means that the binding occurs at run time,based on the type of object.Late binding is also called dynamic binding or runtime binding.

...All method binding in Java uses late binding unless the method is static or final(private methods are implicitly final).

 

Produing the right behavior

一个经典的多态实例:

public class Shape {
 public void draw(){}
 public void erase(){}
}

public class Circle extends Shape {
 public void draw(){
  System.out.println("Circle.draw()");
 }
 public void erase(){
  System.out.println("Circle.erase()");
 }
}

public class Square extends Shape {
 public void draw(){
  System.out.println("Square.draw()");
 }
 public void erase(){
  System.out.println("Square.erase()");
 }
}

public class Triangle extends Shape {
 public void draw(){
  System.out.println("Triangle.draw()");
 }
 public void erase(){
  System.out.println("Triangle.erase()");
 }
}

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();
  }
 }
}

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();
 }
}

输出:

Triangle.draw()
Triangle.draw()
Square.draw()
Triangle.draw()
Square.draw()
Triangle.draw()
Square.draw()
Triangle.draw()
Circle.draw()

上例子类声明均为父类型Shape

Extensibility

...In a well-designed OOP program,most or all of your methods will follow the model of tune() and communicate only with the base-class interface.Such a program is extensible because you can add new functionality by inheriting new data types from the common base class.

表示多态扩展性高的一个实例:

public class Instrument {
 void play(Note n){
  System.out.println("Instrument.play() "+n);
 }
 String what(){return "Instrument";}
 void adjust(){
  System.out.println("Adjusting Instrument");
 }
}

public class Wind extends Instrument {
 void play(Note n){
  System.out.println("Wind.play() "+n);
 }
 String what(){return "Wind";}
 void adjust(){
  System.out.println("Adjusting Wind");
 }
}

public class Percussion extends Instrument {
 void play(Note n){
  System.out.println("Percussion.play() "+n);
 }
 String what(){return "Percussion";}
 void adjust(){
  System.out.println("Adjusting Percussion");
 }
}

public class Stringed extends Instrument {
 void play(Note n){
  System.out.println("Stringed.play() "+n);
 }
 String what(){return "Stringed";}
 void adjust(){
  System.out.println("Adjusting Stringed");
 }
}

public class Brass extends Wind {
 void play(Note n){
  System.out.println("Brass.play() "+n);
 }
 void adjust(){
  System.out.println("Adjusting Brass");
 }
}

public class Woodwind extends Wind {
 void play(Note n){
  System.out.println("Woodwind.play() "+n);
 }
 String what(){return "Woodwind";}
}

public class Music3 {
 public static void tune(Instrument i){
  i.play(Note.MIDDLE_C);
 }
 public static void tuneAll(Instrument[] e){
  for(Instrument i : e)
   tune(i);
 }
 public static void main(String[] args) {
  Instrument[] orchestra = {
    new Wind(),
    new Percussion(),
    new Stringed(),
    new Brass(),
    new Woodwind()
  };
  tuneAll(orchestra);
 }
}

输出:

Wind.play() MIDDLE_C
Percussion.play() MIDDLE_C
Stringed.play() MIDDLE_C
Brass.play() MIDDLE_C
Woodwind.play() MIDDLE_C
比较Music3与Music2的不同之处:Music2 main方法中,乐器声明为各自的类型,Music3 main方法中,乐器声明均为基类Instrument类型(用了一个数组),所以可以使用统一的形参类型:Instrument,而可以自动识别调用各子类中的方法.

...polymorphism is an important technique for the programmer to "separate the things that change from the things that stay the same."

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值