2022-07-28 Java第5章練習——多態(tài)、組合與繼承

題目4

改寫第3題的程序,利用組合來實現(xiàn)類復用。

由于已經(jīng)建立了Person類和它的info方法,因此我再創(chuàng)建一個Teacher類時可以直接將Person組合進來,調(diào)用其info方法,源代碼如下:

package pe;
/**
 * 此為一個Teacher類,演示了通過組合獲得Person類的info方法
 * @author Liu XueZheng
 * @version 1.0
 */
public class Teacher{
    //創(chuàng)建一個Person實例
    private Person p;
    //定義構造器,形參為Person
    public Teacher(Person p){
    //將傳入的實參賦給實例變量p
    this.p = p;
    }
    //創(chuàng)建一個info方法,里面調(diào)用p的info方法
    public void info(String name){
    p.info(name);
    }
    public static void main(String[] args){
        //此時需要顯示創(chuàng)建被組合的對象
    //Object p = new Person();
    var p = new Person();
    //新建一個Teacher對象
        var t = new Teacher(p);
    //調(diào)用t的info方法
    t.info("xiaoTian");
    }
}

這里將Teacher類也放入了pe包內(nèi),在調(diào)用Person類時便可省略路徑名稱。需要注意的一點是在main方法中創(chuàng)建實例時,如果是采用Object p = new Person(); 會引起編譯錯誤。這牽扯到了多態(tài)的問題,等式左邊聲明了p是一個Object類的實例,但等式右邊說明實際執(zhí)行時p是一個Person類實例,在編譯時是按照聲明的類型來的,因此會造成后邊將p作為實參傳入var t = new Teacher(p)時報錯,錯誤如下:


多態(tài)引發(fā)的編譯異常.png

原因就是Tracher構造器方法中的形參是一個Person類型,而傳入的p在編譯時是一個Object類型。
將Object改為var后便不存在這個問題,因為var會自動根據(jù)等式右邊類型推測編譯時類型。程序運行結果如下:


題目4程序運行結果

題目5

定義交通工具、汽車、火車、飛機這些類,注意它們的繼承關
系,為這些類提供超過3個不同的構造器,并通過實例初始化塊提取構
造器中的通用代碼。
首先定義一個交通工具類作為父類,其具有使用壽命、單價、容納人數(shù)三個成員變量。然后創(chuàng)建一個汽車類繼承交通工具類。在交通工具類中利用實例初始化塊對成員變量進行了初始化。源代碼如下:

package vh;
//定義交通工具類
class Vehicle{
    //定義使用壽命
    protected int serviceLife;
    //定義單價
    protected double unitPrice;
    //定義容納人數(shù)
    protected int capacity;
    //定義啟動方法
    public void start(){
    System.out.println("Start");
    }
    //定義實例初始化塊為成員變量賦值
    {
        serviceLife = 20;
        unitPrice = 10.0;
        capacity = 12;
    }
    //定義無參構造器
    public Vehicle(){
    System.out.println("這是Vehicle類的一個無參構造器");
    }
    //定義一個參數(shù)的構造器
    public Vehicle(String firstParam){
    System.out.println("這是Vehicle類的一個參數(shù)的構造器,參數(shù)為:" + firstParam);
    }
    public Vehicle(String firstParam, String secondParam){
    System.out.println("這是Vehicle類的兩個參數(shù)的構造器,參數(shù)為:" + firstParam + ", " + secondParam);
    }
}
//定義汽車類
class Car extends Vehicle{
    //定義輸出信息的info方法
    public void info(){
        System.out.println("Car的使用壽命為:" + serviceLife + "年");
        System.out.println("Car的單價為:" + unitPrice + "萬");
        System.out.println("Car的容納人數(shù)為:" + capacity + "人");
    }
}

public class TestVehicle{
    public static void main(String[] args){
        //定義一個Vehicle實例,使用無參構造器
        var v = new Vehicle();
        //定義一個Vehicle實例,使用一個參數(shù)的構造器
        var vOne = new Vehicle("one");
        //定義一個Vehicle實例,使用兩個參數(shù)的構造器
        var vTwo = new Vehicle("one", "two");
        //定義一個Car實例,使用默認構造器
    var car = new Car();
    //調(diào)用car的info方法
    car.info();
    }
}

輸出結果如下:


題目5程序運行結果

這里由于Car類定義時沒有定義構造器,因此其默認繼承了父類的構造器,相當于系統(tǒng)自動為Car類創(chuàng)建了一個無參構造器,構造器中調(diào)用了父類的無參構造器,如下所示:

public Car(){
    //調(diào)用父類的無參構造器
    super();
}

如果想調(diào)用父類的其他構造器,需要傳入對應參數(shù)。比如讓Car類調(diào)用父類的一個參數(shù)的構造器,代碼如下:

public Car(String oneParam){
    //調(diào)用父類的一個參數(shù)的構造器
    super(oneParam);
}

運行結果如下:


Car的一個參數(shù)構造器

在Car中再新建一個三個參數(shù)的構造器,使其可以對三個成員變量賦值

public Car(int serviceLife, double unitPrice, int capacity){
        this.serviceLife = serviceLife;
    this.unitPrice = unitPrice;
        this.capacity = capacity; 
}

新建一個Car對象并利用三個參數(shù)的構造器進行初始化,打印其成員變量值

var carTwo = new Car(15, 10, 6);
carTwo.info();

結果如下:


新構造器運行結果

由于新構造器沒有顯示調(diào)用父類構造器,因此其隱式地調(diào)用了父類的無參構造器,然后才執(zhí)行子類的新構造器。

?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容