zoukankan      html  css  js  c++  java
  • 多形性

    虽然是第二次看,感觉这部分还是要仔细看。多形性是面向对象编程语言的第三中特性。

    首先是上溯造型(这个是什么意思就不说了),为什么需要上溯造型呢?很多书上都会用“画图”或者“乐器”的程序来和大家解释:

    class Note{
    private int value;
    private Note(int val) { value = val; }
    public static final Note
    middleC
    = new Note(0),
    cSharp
    = new Note(1),
    cFlat
    = new Note(2);
    }
    // Etc.
    class Instrument {
    public void play(Note n) {
    System.out.println(
    "Instrument .play()");
    }
    }
    class Wind extends Instrument {
    public void play(Note n) {
    System.out.println(
    "Wind .play()");
    }
    }
    class Stringed extends Instrument {
    public void play(Note n) {
    System.out.println(
    "Stringed .play()");
    }
    }
    class Brass extends Instrument {
    public void play(Note n) {
    System.out.println(
    "Brass .play()");
    }
    }
    public class test {
    public static void tune(Wind i) {
    i.play(Note .middleC);
    }
    public static void tune(Stringed i) {
    i.play(Note .middleC);
    }
    public static void tune(Brass i) {
    i.play(Note .middleC);
    }
    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()
    Stringed.play()
    Brass.play()

    神奇吧,但是程序是怎么知道的?显然在编译的时候确定是不可能的。所以这只能“运行期绑定”了。那“运行期绑定”是怎么实现的?一般认为是在对象中安插关于类型的特殊信息(细节我还不清楚)。有了这个显然会给我们带来极大的方便,因为只要你是乐器,我调用演奏的方法你就能正确地发出声音。

    继承不断地进化,就出现了“抽象类”,只要用“abstract”来修饰一个类就可以了(如果有抽象方法的话必须为抽象类):

     1 import java.util.*;
    2 abstract class Instrument {
    3 int i;
    4 public abstract void play();
    5 public String what() {
    6 return "Instrument";
    7 }
    8 public abstract void adjust();
    9 }
    10 class Wind extends Instrument {
    11 public void play() {
    12 System.out.println("Wind.play()");
    13 }
    14 public String what() { return "Wind"; }
    15 public void adjust() {}
    16 }
    17 class Percussion extends Instrument {
    18 public void play() {
    19 System.out.println("Percussion.play()");
    20 }
    21 public String what() { return "Percussion"; }
    22 public void adjust() {}
    23 }
    24 class Stringed extends Instrument {
    25 public void play() {
    26 System.out.println("Stringed.play()");
    27 }
    28 public String what() { return "Stringed"; }
    29 public void adjust() {}
    30 }
    31 class Brass extends Wind {
    32 public void play() {
    33 System.out.println("Brass.play()");
    34 }
    35 public void adjust() {
    36 System.out.println("Brass.adjust()");
    37 }
    38 }
    39 class Woodwind extends Wind {
    40 public void play() {
    41 System.out.println("Woodwind.play()");
    42 }
    43 public String what() { return "Woodwind"; }
    44 }
    45 public class test {
    46 static void tune(Instrument i) {
    47 i.play();
    48 }
    49 static void tuneAll(Instrument[] e) {
    50 for(int i = 0; i < e.length; i++)
    51 tune(e[i]);
    52 }
    53 public static void main(String[] args) {
    54 Instrument[] orchestra = new Instrument[5];
    55 int i = 0;
    56 orchestra[i++] = new Wind();
    57 orchestra[i++] = new Percussion();
    58 orchestra[i++] = new Stringed();
    59 orchestra[i++] = new Brass();
    60 orchestra[i++] = new Woodwind();
    61 tuneAll(orchestra);
    62 }
    63 }

    自从有了抽象类,就不能随随便便地申请对象了,还得乖乖地实现抽象方法。既然已经到这个地步了,那和不走的更远?

     1 import java.util.*;
    2 interface CanFight {
    3 void fight();
    4 }
    5 interface CanSwim {
    6 void swim();
    7 }
    8 interface CanFly {
    9 void fly();
    10 }
    11 class ActionCharacter {
    12 public void fight() {}
    13 }
    14 class Hero extends ActionCharacter implements CanFight, CanSwim, CanFly {
    15 public void swim() {}
    16 public void fly() {}
    17 }
    18 public class test {
    19 static void t(CanFight x) { x.fight(); }
    20 static void u(CanSwim x) { x.swim(); }
    21 static void v(CanFly x) { x.fly(); }
    22 static void w(ActionCharacter x) { x.fight(); }
    23 public static void main(String[] args) {
    24 Hero i = new Hero();
    25 t(i); // Treat it as a CanFight
    26 u(i); // Treat it as a CanSwim
    27 v(i); // Treat it as a CanFly
    28 w(i); // Treat it as an ActionCharacter
    29 }
    30 }

    接口,貌似是抽象类的进化,但是貌似没那么简单。可以“implements”多个接口,“interface”里面的东西全部被认为是“static&final”的(这这点很容易理解)。而且对接口更好的理解是“协议”。实现了多个接口的类可以上溯为多个类型(这个很好理解哈)。这个地方有个“static&final”引起的小插曲,应该算是Java怎么实现“enum”的吧:

     1 public final class test {
    2 private String name;
    3 private test(String nm) { name = nm; }
    4 public String toString() { return name; }
    5 public final static test
    6 JAN = new test("January"),
    7 FEB = new test("February"),
    8 MAR = new test("March"),
    9 APR = new test("April"),
    10 MAY = new test("May"),
    11 JUN = new test("June"),
    12 JUL = new test("July"),
    13 AUG = new test("August"),
    14 SEP = new test("September"),
    15 OCT = new test("October"),
    16 NOV = new test("November"),
    17 DEC = new test("December");
    18 public final static test[] month = {
    19 JAN, JAN, FEB, MAR, APR, MAY, JUN,
    20 JUL, AUG, SEP, OCT, NOV, DEC
    21 };
    22 public static void main(String[] args) {
    23 test m = test.JAN;
    24 System.out.println(m);
    25 m = test.month[12];
    26 System.out.println(m);
    27 System.out.println(m == test.DEC);
    28 System.out.println(m.equals(test.DEC));
    29 }
    30 }

    有值有类型安全检查,还算不错吧?不过第一次见到这个方法好像不是在这本书上。

    关于继承方面的就到此为止,下面开始“内部类”:

     1 public class test {
    2 class Contents {
    3 private int i = 11;
    4 public int value() { return i; }
    5 }
    6 class Destination {
    7 private String label;
    8 Destination(String whereTo) {
    9 label = whereTo;
    10 }
    11 String readLabel() { return label; }
    12 }
    13 public void ship(String dest) {
    14 Contents c = new Contents();
    15 Destination d = new Destination(dest);
    16 }
    17 public static void main(String[] args) {
    18 test p = new test();
    19 p.ship("Tanzania");
    20 }
    21 }

    看着实现起来很简单吧!其实感觉这个东西本来就不难,关键是怎么用吧。还有就是匿名类。如果定义了一个匿名类,并想使用在匿名类内部使用外部类定义的一个对象,编译器要求外部类对象必须为final类型的(想想为什么?http://blog.csdn.net/cnitcastsdut/article/details/6020221)。这种写法是为了方便吧:

     1 interface Destination {
    2 String readLabel();
    3 }
    4 public class test {
    5 public Destination dest(final String dest) {
    6 return new Destination() {
    7 private String label = dest;
    8 public String readLabel() { return label; }
    9 };
    10 }
    11 public static void main(String[] args) {
    12 test p = new test();
    13 Destination d = p.dest("Tanzania");
    14 }
    15 }

    威为什么内部类可以访问封装类?是因为在内部类的对象里面保存了一个外部类的指针。内部类拥有对封装类所有元素的访问权限。那如果内部类是“static”呢?创建一个static的内部类对象是不需要一个外部类对象,所以不能从static内部类的一个对象访问一个外部类对象的。

     1 abstract class Contents {
    2 abstract public int value();
    3 }
    4 interface Destination {
    5 String readLabel();
    6 }
    7 public class test {
    8 private static class PContents extends Contents {
    9 private int i = 11;
    10 public int value() { return i; }
    11 }
    12 protected static class PDestination implements Destination {
    13 private String label;
    14 private PDestination(String whereTo) {
    15 label = whereTo;
    16 }
    17 public String readLabel() { return label; }
    18 }
    19 public static Destination dest(String s) {
    20 return new PDestination(s);
    21 }
    22 public static Contents cont() {
    23 return new PContents();
    24 }
    25 public static void main(String[] args) {
    26 Contents c = cont();
    27 Destination d = dest("Tanzania");
    28 }
    29 }

    怎么去声明一个内部类的对象?其实看起来并不奇怪哈,其实继承内部类的时候也是这么写的。更神奇的是内部类可以覆盖(hh)。

     1 public class test {
    2 class Contents {
    3 private int i = 11;
    4 public int value() { return i; }
    5 }
    6 class Destination {
    7 private String label;
    8 Destination(String whereTo) {
    9 label = whereTo;
    10 }
    11 String readLabel() { return label; }
    12 }
    13 public static void main(String[] args) {
    14 test p = new test();
    15 // Must use instance of outer class
    16 // to create an instances of the inner class:
    17 test.Contents c = p.new Contents();
    18 test.Destination d = p.new Destination("Tanzania");
    19 }
    20 }

  • 相关阅读:
    Legendary Items-微软2017实习生笔试第一题
    (转载)华为离职副总裁徐家骏:年薪千万的工作感悟
    【AtCoder Regular Contest 092】C.2D Plane 2N Points【匈牙利算法】
    poj 2236【并查集】
    poj 2431 【优先队列】
    poj 3280【区间dp】
    uva 10453 【回文串区间dp】
    uva 10739【基础(区间)dp】
    poj 2385【动态规划】
    poj 2229 【完全背包dp】【递推dp】
  • 原文地址:https://www.cnblogs.com/ggzwtj/p/2117728.html
Copyright © 2011-2022 走看看