題目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)時報錯,錯誤如下:

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

題目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();
}
}
輸出結果如下:

這里由于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ù)的構造器,使其可以對三個成員變量賦值
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í)行子類的新構造器。