1. 程式人生 > >複用類一

複用類一

(一) 組合語法

每一個非基本型別的物件都有一個toString()方法,而且當編譯器需要一個String而你只有一個物件時,該方法就會被呼叫。如下:

class WaterSourse {
	private String s;

	WaterSourse() {
		System.out.println("WaterSource");
		s = "Constructed";
	}
	
	public String toString() {
		return s;
	}
}

public class SprinklerSystem {
	private String value1, value2, value3, value4;
	private WaterSourse source = new WaterSourse();
	private int i;
	private float f;

	public String toString() {
		return "value1=" + value1 + " " + "value1=" + value2 + " " + "value1=" + value3 + " " + "value1=" + value4
				+ "\n" + "i=" + i + " " + "f=" + f + " " + "source=" + source;
	}

	public static void main(String[] args) {
		SprinklerSystem sprinkler = new SprinklerSystem();
		System.out.println(sprinkler);
	}

}

結果為:

WaterSource
value1=null value1=null value1=null value1=null
i=0 f=0.0 source=Constructed

編譯器並不是簡單地為每一個引用都建立預設物件,那樣會增加不必要的負擔,初始化引用可以在如下位置:
(1)定義物件的地方(使得他們總能夠在構造器被呼叫之前)
(2)在類的構造器中
(3)在使用這些物件之前(惰性初始化),減少額外負擔
(4)使用例項初始化
如下:

class Soap {
	private String s;

	Soap() {
		System.out.println("soup()");
		s = "Constructed";
	}
	
	public String toString() {
		return s;
	}
}

public class Bath {
	private String s1 = "happy", s2 = "heappy", s3, s4;// 在定義物件時初始化。即在構造器被呼叫之前初始化。
	private Soap castile;
	private int i = 90;
	private float toy;

	public Bath() {
		// i = 56; //可以看出例項初始化子句是在構造器執行前執行的。再次賦值。
		System.out.println("Inside Bath()");
		s3 = "Joy";
		toy = 3.14f;
		castile = new Soap();
	}

	{
		i = 47; // 例項初始化
	}

	public String toString() {
		if (s4 == null) { // 惰性初始化.減少不必要的負擔
			s4 = "JOY";
		}
		return "s1=" + s1 + " " + "s2=" + s2 + " " + "s3=" + s3 + " " + "s4=" + s4 + " \n" + "i=" + i + "\n" + "toy="
				+ toy + "\n" + "castille=" + castile;
	}

	public static void main(String[] args) {

		System.out.println(new Bath());
	}

}

結果為:

i=47
toy=3.14
castille=Constructed

(二) 繼承語法

其他包中的某個類若要從Cleanser中繼承,則只能訪問public成員。
所以為了繼承,一般的規則是將所有的資料成員都指定為private,將所有的方法都指定為public。

class Cleanser {
	private String s = "Cleanser";

	void append(String a) {
		s += a;
	}

	public void dilute() {
		append("dilute() ");
	}

	protected void apply() {
		append("apply()");
	}

	void scrub() {
		append("scrube() ");
	}

	public String toString() {
		return s;
	}

	public static void main(String[] args) {
		Cleanser cleanser = new Cleanser();
		cleanser.dilute();
		cleanser.scrub();
		cleanser.apply();
		System.out.println(cleanser);
	}

}

public class Detergent extends Cleanser {
	public void scrub() {
		append("Detergent scube ");
		super.scrub();
	}

	public void foam() {
		append("foam() ");
	}

	/*
	 * public String toString() { return "aaa"; }
	 */

	public static void main(String[] args) {
		Detergent d = new Detergent();
		Cleanser c = new Cleanser();
		d.dilute();
		d.foam();
		d.scrub();
		d.apply();
		System.out.println(d);
		System.out.println("Testing base class:");
		Cleanser.main(args);

	}

}

結果為:

Cleanserdilute() foam() Detergent scube scrube() apply()
Testing base class:
Cleanserdilute() scrube() apply()

一 初始化基類

(1)當建立了一個匯出類的物件時,該物件包含了一個基類的子物件。這個子物件與基類直接建立的物件是一樣的,區別在於:後者來自於外部,而基類的子物件被包裝在匯出類物件的內部。
(2)對基類子物件的初始化: 在構造器中呼叫基類構造器來執行初始化。
(3)Java會自動在到處類的構造其中插入對基類構造器的呼叫。
(4)基類在匯出類的構造器可以訪問它之前,就已經完成了初始化。
如下:

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

class Drawing extends Art {
	Drawing() {
		System.out.println("Drawing()");
	}
}

public class Cartoon extends Drawing {
	Cartoon() {
		System.out.println("Cartoon");
	}

	public static void main(String[] args) {
		Cartoon cartoon = new Cartoon();

	}
}

結果為:

Art()
Drawing()
Cartoon

二 帶引數的構造器

(1)如果沒有預設的基類構造器,或者想要呼叫一個帶引數的基類構造器,就必須要用關鍵字super顯示的編寫呼叫基類構造器的語句,並且配以適當的引數列表。
(2)呼叫基類構造器必須是在匯出類構造器中要做的第一件事。
如下:

lass Game {
	Game(int i) {
		System.out.println("Game()");
	}
}

class BoardGame extends Game {
	BoardGame(int i) {
		super(i); // 呼叫基類構造器必須是匯出類構造器的第一條語句

		System.out.println("B");
		// super(i);
	}
}

public class Chess extends BoardGame {

	Chess() {
		super(11);
		System.out.println("Chess");
	}

	public static void main(String[] args) {
		Chess chess = new Chess();
	}

}

結果為:

Game()
B
Chess