1. 程式人生 > >Thinking in Java 第四版完整版 第八章練習題 多型

Thinking in Java 第四版完整版 第八章練習題 多型

Thinking in Java 第四版完整版 第八章練習題,記錄一下(jdk1.8.0)

1.

/**
 * 練習1:建立一個Cycle類,它具有子類Unicycle、Bicycle和
 * Tricycle。演示每一個型別的示例都可以經由ride()方法向上
 * 轉型為Cycle。
 * @author admin11
 * @date 2018年3月28日
 */
class Cycle {}

class Unicycle extends Cycle {}

class Bicycle extends Cycle {}

class Tricycle extends Cycle {}

public
class Exercise801 { public static void ride(Cycle cycle) {} public static void main(String[] args) { ride(new Unicycle()); ride(new Bicycle()); ride(new Tricycle()); } }

2.

/**
 * 練習2:在幾何圖形的示例中新增@Override註解。
 * @author admin11
 * @date 2018年3月28日
 */
 public class
Shape {
public void draw() {} public void erase() {} }
public class Circle extends Shape {
    @Override
    public void draw() {
        System.out.println("Circle.draw()");
    }
    @Override
    public void erase() {
        System.out.println("Circle.erase()");
    }
}
public class
Square extends Shape{
@Override public void draw() { System.out.println("Square.draw()"); } @Override public void erase() { System.out.println("Square.erase()"); } }
public class Triangle extends Shape{
    @Override
    public void draw() {
        System.out.println("Triangle.draw()");
    }
    @Override
    public void erase() {
        System.out.println("Triangle.erase()");
    }
}
import java.util.Random;

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 shape : s) {
            shape.draw();
        }
    }
}

這裡寫圖片描述

3.

/**
 * 練習3:在基類Shapes.java中新增一個新方法,用於列印一條訊息,
 * 但匯出類中不要覆蓋這個方法。請解釋發生了什麼。現在,在其中一個匯出
 * 類中覆蓋該方法,而在其他的匯出類中不予覆蓋,觀察又有什麼發生。最後,
 * 在所有的匯出類中覆蓋這個方法。
 * @author admin11
 * @date 2018年3月28日
 */
public class Shape {
    public void draw() {}
    public void erase() {}
    public void testPrint() {
        System.out.println("shape.testPrint()");
    }
}
public class Circle extends Shape {
    @Override
    public void draw() {
        System.out.println("Circle.draw()");
    }
    @Override
    public void erase() {
        System.out.println("Circle.erase()");
    }
    @Override
    public void testPrint() {
        System.out.println("Circle.testPrint()");
    }
}
public class Square extends Shape{
    @Override
    public void draw() {
        System.out.println("Square.draw()");
    }
    @Override
    public void erase() {
        System.out.println("Square.erase()");
    }
    @Override
    public void testPrint() {
        System.out.println("Square.testPrint()");
    }
}
public class Triangle extends Shape{
    @Override
    public void draw() {
        System.out.println("Triangle.draw()");
    }
    @Override
    public void erase() {
        System.out.println("Triangle.erase()");
    }
    @Override
    public void testPrint() {
        System.out.println("Triangle.testPrint()");
    }
}
import java.util.Random;

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 shape : s) {
            shape.draw();
            shape.testPrint();
        }
    }
}

這裡寫圖片描述
這裡寫圖片描述
這裡寫圖片描述

4.

/**
 * 練習4:向Shapes.java中新增一個新的Shape型別,並在main()
 * 方法中驗證:多型對新型別的作用是否與在舊型別中的一樣。
 * @author admin11
 * @date 2018年3月28日
 */
class Shape {
    public void draw() {}
    public void erase() {}
    public void testPrint() {
        System.out.println("shape.testPrint()");
    }
}

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

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

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

class newShape extends Shape{
    @Override
    public void draw() {
        System.out.println("newShape.draw()");
    }
    @Override
    public void erase() {
        System.out.println("newShape.erase()");
    }
    @Override
    public void testPrint() {
        System.out.println("newShape.testPrint()");
    }
}

public class Exercise804 {
    public static void main(String[] args) {
        Shape[] sp = {new Circle(), new Square(),
                new Triangle(), new newShape()};
        for (Shape shape : sp) {
            shape.draw();
            shape.erase();
            shape.testPrint();
        }
    }
}

這裡寫圖片描述

5.

/**
 * 練習5:以練習1為基礎,在Cycle中新增wheels()方法,它將返回
 * 輪子的數量。修改ride()方法,讓它呼叫wheels()方法,並驗證
 * 多型起作用了。
 * @author admin11
 * @date 2018年3月28日
 */
class Cycle {
    public String wheels() {
        return "Cycle wheels : none";
    }
}

class Unicycle extends Cycle {
    @Override
    public String wheels() {
        return "Unicycle wheels : 4";
    }
}

class Bicycle extends Cycle {
    @Override
    public String wheels() {
        return "Bicycle wheels : 2";
    }
}

class Tricycle extends Cycle {
    @Override
    public String wheels() {
        return "Tricycle wheels : 3";
    }
}

public class Exercise805 {
    public static void ride(Cycle cycle) {
        System.out.println(cycle.wheels());
    }
    public static void main(String[] args) {
        Cycle[] c = {new Unicycle(), new Bicycle(),
                new Tricycle()};
        for (Cycle cycle : c) {
            ride(cycle);
        }
    }
}

這裡寫圖片描述

6.

/**
 * 練習6:修改Music3.java,使what()方法成為根Object的
 * toString()方法。試用System.out.println()方法列印
 * Instrument物件(不用向上轉型)。
 * @author admin11
 * @date 2018年3月28日
 */
enum Note {
    MIDDLE_C, C_SHARP, B_FLAT;
}

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

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

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

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

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

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

public class Exercise806 {
    static Instrument[] orchestra = {
            new Wind(),
            new Percussion(),
            new Stringed(),
            new Brass(),
            new Woodwind()
    };

    public static void printAll(Instrument[] e) {
        for (Instrument instrument : e) {
            System.out.println(instrument);
        }
    }

    public static void main(String[] args) {
        printAll(orchestra);
    }
}

這裡寫圖片描述

7.

/**
 * 練習7:向Music3.java新增一個新的型別Instrument,
 * 並驗證多型性是否作用於所新增的新型別。
 * @author admin11
 * @date 2018年3月28日
 */
enum Note {
    MIDDLE_C, C_SHARP, B_FLAT;
}

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

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

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

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

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

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

class Electronic extends Instrument {
    @Override
    void play(Note n) {
        System.out.println("Electronic.play() " + n);
    }
    @Override
    public String toString() {
        return "Electronic";
    }
    @Override
    void adjust() {
        System.out.println("Adjusting Electronic");
    }
}

public class Exercise807 {

    public static void main(String[] args) {
        Instrument[] orchestra = {
                new Wind(),
                new Percussion(),
                new Stringed(),
                new Brass(),
                new Woodwind(),
                new Electronic()
        };

        for (Instrument instrument : orchestra) {
            instrument.play(Note.MIDDLE_C);
            instrument.adjust();
            System.out.println(instrument);
        }
    }
}

這裡寫圖片描述

8.

import java.util.Random;
/**
 * 練習8:修改Music3.java,使其可以像Shapes.java中的方式
 * 那樣隨機建立Instrument物件。
 * @author admin11
 * @date 2018年3月28日
 */
enum Note {
    MIDDLE_C, C_SHARP, B_FLAT;
}

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

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

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

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

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

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

class Electronic extends Instrument {
    @Override
    void play(Note n) {
        System.out.println("Electronic.play() " + n);
    }
    @Override
    public String toString() {
        return "Electronic";
    }
    @Override
    void adjust() {
        System.out.println("Adjusting Electronic");
    }
}

class InstrumentGenerator {
    public Instrument next() {
        switch (new Random().nextInt(6)) {
        default:
        case 0:
            return new Wind();
        case 1:
            return new Percussion();
        case 2:
            return new Stringed();
        case 3:
            return new Brass();
        case 4:
            return new Woodwind();
        case 5:
            return new Electronic();
        }
    }
}

public class Exercise808 {
    public static void main(String[] args) {
        InstrumentGenerator gen = new InstrumentGenerator();
        for (int i = 0; i < 10; i++) {
            System.out.println(gen.next());
        }
    }
}

這裡寫圖片描述

9.

/**
 * 練習9:建立Rodent(齧齒動物):Mouse(老鼠),Gerbil(鼴鼠),
 * Hamster(大頰鼠),等等這樣一個的繼承層次結構。在基類中,提供對所
 * 有的Rodent都通用的方法,在匯出類中,根據特定的Rodent型別覆蓋
 * 這些方法,以便它們執行不同的行為。建立一個Rodent陣列,填充不同
 * 的Rodent型別,然後呼叫基類方法,觀察發生什麼情況。
 * @author admin11
 * @date 2018年3月28日
 */
class Rodent {
    public void eat() {
        System.out.println("eat...");
    }
    public void sleep() {
        System.out.println("sleep...");
    }
}

class Mouse extends Rodent{
    @Override
    public void eat() {
        System.out.println("Mouse eat...");
    }
    @Override
    public void sleep() {
        System.out.println("Mouse sleep...");
    }
}

class Gerbil extends Rodent {
    @Override
    public void eat() {
        System.out.println("Gerbil eat...");
    }
    @Override
    public void sleep() {
        System.out.println("Gerbil sleep...");
    }
}

class Hamster extends Rodent {
    @Override
    public void eat() {
        System.out.println("Hamster eat...");
    }
    @Override
    public void sleep() {
        System.out.println("Hamster sleep...");
    }
}

public class Exercise809 {
    public static void main(String[] args) {
        Rodent[] rd = {
                new Mouse(),
                new Gerbil(),
                new Hamster()
        };
        for (Rodent rodent : rd) {
            rodent.eat();
            rodent.sleep();
        }
    }
}

這裡寫圖片描述

10.

/**
 * 練習10:建立一個包含兩個方法的基類。在第一個方法中可以呼叫第二個
 * 方法。然後產生一個繼承自該基類的匯出類,且覆蓋基類中的第二個方法。
 * 為該匯出類建立一個物件,將它向上轉型到基型別並呼叫第一個方法,解
 * 釋發生的情況。
 * @author admin11
 * @date 2018年3月28日
 */
class TwoMethods {
    public void m1() {
        System.out.println("Inside m1, calling m2");
        m2();
    }
    public void m2() {
        System.out.println("Inside m2");
    }
}

public class Exercise810 extends TwoMethods{
    public void m2() {
        System.out.println("Inside Exercise810.m2");
    }
    public static void main(String[] args) {
        TwoMethods t = new Exercise810();
        t.m1();
        // 呼叫匯出類的m1()方法,m1()方法呼叫了m2,
        // m2在匯出類被重寫了
    }
}

這裡寫圖片描述

11.

/**
 * 練習11:向Sandwich.java中新增Pickle類。
 * @author admin11
 * @date 2018年3月30日
 */
class Meal {
    Meal() {
        System.out.println("Meal()");
    }
}

class Bread {
    Bread() {
        System.out.println("Bread()");
    }
}

class Cheese {
    Cheese() {
        System.out.println("Cheese()");
    }
}

class Lettuce {
    Lettuce() {
        System.out.println("Lettuce");
    }
}

class Lunch extends Meal {
    Lunch() {
        System.out.println("Lunch()");
    }
}

class PortableLunch extends Lunch {
    PortableLunch() {
        System.out.println("PortableLunch()");
    }
}

class Pickle {
    Pickle() {
        System.out.println("Pickle()");
    }
}

public class Sandwich extends PortableLunch {
    private Bread b = new Bread();
    private Cheese c = new Cheese();
    private Lettuce l = new Lettuce();
    private Pickle p = new Pickle();
    public Sandwich() {
        System.out.println("Sandwich()");
    }
    public static void main(String[] args) {
        new Sandwich();
    }
}

這裡寫圖片描述

12.

/**
 * 練習12:修改練習9,使其能夠演示基類和匯出類的初始化順序。然後
 * 向基類和匯出類中新增成員物件,並說明構建期間初始化發生的順序。
 * @author admin11
 * @date 2018年3月30日
 */
class Member {
    public Member(String id) {
        System.out.println("Member constructor " + id);
    }
}

class Rodent2 {
    Member m1 = new Member("r1"),
            m2 = new Member("r2");
    public Rodent2() {
        System.out.println("Rodent constructor");
    }
    public void hop() {
        System.out.println("Rodent hopping");
    }
    public void scurry() {
        System.out.println("Rodent scurrying");
    }
    public void reproduce() {
        System.out.println("Making more Rodents");
    }
    public String toString() {
        return "Rodent";
    }
}

class Mouse2 extends Rodent2 {
    Member m1 = new Member("m1"),
            m2 = new Member("m2");
    public Mouse2() {
        System.out.println("Mouse2 constructor");
    }
    public void hop() {
        System.out.println("Mouse2 hopping");
    }
    public void scurry() {
        System.out.println("Mouse2 scurrying");
    }
    @Override
    public void reproduce() {
        System.out.println("Making more Mice");
    }
    @Override
    public String toString() {
        return "Mouse";
    }
}

class Gerbil2 extends Rodent2 {
    Member m1 = new Member("g1"),
            m2 = new Member("g2");
    public Gerbil2() {
        System.out.println("Gerbil2 constructor");
    }
    @Override
    public void hop() {
        System.out.println("Gerbil2 hopping");
    }
    @Override
    public void scurry() {
        System.out.println("Gerbil2 scurrying");
    }
    @Override
    public void reproduce() {
        System.out.println("Making more Gerbils");
    }
    @Override
    public String toString() {
        return "Gerbil";
    }
}

class Hamster2 extends Rodent2 {
    Member m1 = new Member("h1"),
            m2 = new Member("h2");
    public Hamster2() {
        System.out.println("Hamster constructor");
    }
    @Override
    public void hop() {
        System.out.println("Hamster hopping");
    }
    @Override
    public void scurry() {
        System.out.println("Hamster scurrying");
    }
    @Override
    public void reproduce() {
        System.out.println("Making more Hamsters");
    }
    @Override
    public String toString() {
        return "Hamster";
    }
}

public class Exercise812 {
    // 先初始化基類的成員變數,呼叫基類的構造方法;
    // 然後初始化匯出類的成員變數,呼叫匯出類的構造方法。
    public static void main(String[] args) {
        new Hamster2();
    }
}

這裡寫圖片描述

13.

/**
 * 練習13:在ReferenceCounting.java中新增一個finalize()
 * 方法,用來校驗終止條件。
 * @author admin11
 * @date 2018年3月30日
 */
class Shared {
    private int refcount = 0;
    private static int counter = 0;
    private int id = counter++;
    public Shared() {
        System.out.println("Creating " + this);
    }
    public void addRef() {
        refcount++;
    }
    protected void dispose() {
        if(--refcount == 0) {
            System.out.println("Disposing " + this);
        }
    }
    protected void finalize() {
        if(refcount != 0) {
            System.out.println("Error: object is not properly cleaned-up!");
        }
    }
    @Override
    public String toString() {
        return "Shared" + id;
    }
}

class Composing {
    private Shared shared;
    private static int counter = 0;
    private int id = counter++;
    public Composing(Shared shared) {
        System.out.println("Creating " + this);
        this.shared = shared;
        this.shared.addRef();
    }
    protected void dispose() {
        System.out.println("disposing" + this);
        shared.dispose();
    }
    @Override
    public String toString() {
        return "Composing " + id;
    }
}

public class Exercise813 {
    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();
        }
        System.gc();
        new Composing(new Shared());
        System.gc();
    }
}

這裡寫圖片描述

14.

/**
 * 練習14:修改練習12,使得其某個成員物件變為具有引用計數的共享物件,
 * 並證明它可以正確執行。
 * @author admin11
 * @date 2018年3月30日
 */
class NonSharedMember {
    public NonSharedMember(String id) {
        System.out.println("Non shared member constructor " + id);
    }
}

class SharedMember {
    private int refcount;
    public void addRef() {
        System.out.println("Number of references " + ++refcount);
    }
    protected void dispose() {
        if(--refcount == 0) {
            System.out.println("Disposing " + this);
        }
    }
    public SharedMember() {
        System.out.println("Shared member constructor");
    }
    @Override
    public String toString() {
        return "Shared member";
    }
}

class Rodent3 {
    private SharedMember m;
    NonSharedMember m1 = new NonSharedMember("r1"),
            m2 = new NonSharedMember("r2");
    public Rodent3(SharedMember sm) {
        System.out.println("Rodent constructor");
        m = sm;
        m.addRef();
    }
    public void hop() {
        System.out.println("Rodent hopping");
    }
    public void scurry() {
        System.out.println("Rodent scurrying");
    }
    public void reproduce() {
        System.out.println("Making more Rodents");
    }
    public void dispose() {
        System.out.println("Disposing " + this);
        m.dispose();
    }
    @Override
    public String toString() {
        return "Rodent";
    }
}

class Mouse3 extends Rodent3 {
    NonSharedMember m1 = new NonSharedMember("m1"),
            m2 = new NonSharedMember("m2");
    public Mouse3(SharedMember sm) {
        super(sm);
        System.out.println("Mouse constructor");
    }
    @Override
    public void hop() {
        System.out.println("Mouse hopping");
    }
    @Override
    public void scurry() {
        System.out.println("Mouse scurring");
    }
    @Override
    public