1. 程式人生 > >繼承的概述及特點,方法重寫的應用場景&注意事項

繼承的概述及特點,方法重寫的應用場景&注意事項

第1章 繼承
1.1 繼承的概述
在現實生活中,繼承一般指的是子女繼承父輩的財產。在程式中,繼承描述的是事物之間的所屬關係,通過繼承可以使多種事物之間形成一種關係體系。
1.2 繼承的格式&使用
在程式中,如果想宣告一個類繼承另一個類,需要使用extends關鍵字。

    格式:
    class 子類 extends 父類 {}

1.3 繼承的特點
在類的繼承中,需要注意一些問題,具體如下:
1、在Java中,類只支援單繼承,不允許多繼承,也就是說一個類只能有一個直接父類,例如下面這種情況是不合法的。
class A{}
class B{}
class C extends A,B{} // C類不可以同時繼承A類和B類
2、多個類可以繼承一個父類,例如下面這種情況是允許的。
class A{}
class B extends A{}
class C extends A{} // 類B和類C都可以繼承類A
3、在Java中,多層繼承是可以的,即一個類的父類可以再去繼承另外的父類,例如C類繼承自B類,而B類又可以去繼承A類,這時,C類也可稱作A類的子類。下面這種情況是允許的。
class A{}
class B extends A{} // 類B繼承類A,類B是類A的子類
class C extends B{} // 類C繼承類B,類C是類B的子類,同時也是類A的子類
4、在Java中,子類和父類是一種相對概念,也就是說一個類是某個類父類的同時,也可以是另一個類的子類。例如上面的這種情況中,B類是A類的子類,同時又是C類的父類

package demo;

/*
 * Java中繼承的特點:
 * 			Java語言只支援單一繼承,只能繼承一個父類(一個兒子只能有一個親爹)
 * 			Java語言支援多層繼承(一個兒子可以有一個親爹,還可以有一個親爺爺)
 * 
 */
public class ExtendsDemo2 {
	public static void main(String[] args) {
		LOL l = new LOL();
		l.update();
		l.start();
	}
}

class Game {
	public void start() {
		System.out.println("遊戲啟動了");
	}
}

class PCGame extends Game {
	public void update() {
		System.out.println("PCGame更新了");
	}
}

class MobileGame extends Game {
	public void update() {
		System.out.println("MobileGame更新了");
	}
}

class LOL extends PCGame {

}

1.4 繼承中成員變數的特點
A:子類只能獲取父類非私有成員
子父類中成員變數的名字不一樣直接獲取父類的成員變數
子父類中成員變數名字是一樣的獲取的是子類的成員變數

B:就近原則:誰離我近我 就用誰
如果有區域性變數就使用區域性變數
如果沒有區域性變數,有子類的成員變數就使用子類的成員變數
如果沒有區域性變數和子類的成員變數,有父類的成員變數就使用父類的成員變數
C: super:可以獲取父類的成員變數和成員方法,用法和this是相似的

package demo;
/*
 * 繼承中成員變數的特點
 * 		子類只能獲取父類非私有成員
 * 		子父類中成員變數的名字不一樣直接獲取父類的成員變數
 * 		子父類中成員變數名字是一樣的獲取的是子類的成員變數
 * 
 * 就近原則:誰離我近我就用誰
 * 		如果有區域性變數就使用區域性變數
 * 		如果沒有區域性變數,有子類的成員變數就使用子類的成員變數
 * 		如果沒有區域性變數和子類的成員變數,有父類的成員變數就使用父類的成員變數
 * 		啥都沒有,出錯了!!!
 * 
 * super:可以獲取父類的成員變數和成員方法,用法和this是相似的
 */
public class ExtendsDemo2 {
	public static void main(String[] args) {
		Kid3 k = new Kid3();
		k.show();
	}
}

class Dad3 {
	String name = "建霖";
}

class Kid3 extends Dad3 {
	String name = "四蔥";

	public void show() {
		String name = "五蔥";

		System.out.println(super.name);
		System.out.println(this.name);
		System.out.println(name);
	}
}

1.5 繼承中成員方法的特點&方法重寫
1.5.1 案例程式碼四
A:子類中沒有這個方法,呼叫父類的

package demo;

/*
 * 繼承中成員方法的特點
 * 		子類中沒有這個方法,呼叫父類的
 
 
 */
public class ExtendsDemo2 {
	public static void main(String[] args) {
		Kid4 k = new Kid4();
		k.eat();
	}
}

class Dad4 {
	public void eat() {
		System.out.println("小酌兩口");
		System.out.println("去睡覺了");
	}
}

class Kid4 extends Dad4 {

}

1.5.2 案例程式碼五
B: 子類中重寫了這個方法,呼叫子類的
方法的重寫:在子父類當中,子類的方法和父類的完全一樣,子類重寫了父類的方法(覆蓋),當子類重寫了父類的方法之後,使用子類物件呼叫的就是子類的方法

package demo;
/*
 * 繼承中成員方法的特點
 * 		子類中沒有這個方法,呼叫父類的
 * 		子類中重寫了這個方法,呼叫子類的
 * 
	方法的重寫:在子父類當中,子類的方法和父類的完全一樣,子類重寫了父類的方法(覆蓋),當子類重寫了父類的方法之後,使用子類物件呼叫的就是子類的方法
 	方法的過載:在一個類中,有多個重名的方法,但是其引數不一樣(引數的個數,引數的型別,引數的順序),和返回值無關
 
 */
public class ExtendsDemo2 {
	public static void main(String[] args) {
		Kid4 k = new Kid4();
		k.eat();
	}
}

class Dad4 {
	public void eat() {
		System.out.println("小酌兩口");
		System.out.println("去睡覺了");
	}
}

class Kid4 extends Dad4 {
	public void eat() {
		System.out.println("好好吃飯");
	}
}

1.6 方法重寫的應用場景&注意事項
方法重寫的應用場景:當父類的方法不能完全滿足子類使用的時候,既可以保留父類的功能(沿襲、傳承),還可以有自己特有的功能
方法重寫的注意事項:
不可以重寫父類私有的成員方法,壓根就看不到父類的私有成員
子類重寫父類方法,許可權必須大於等於父類方法的許可權
註解
@Override:方法重寫,說明下面的方法是重寫父類的方法

package demo;

/*
 * 	方法重寫的應用場景:當父類的方法不能完全滿足子類使用,這個時候子類重寫父類的方法,
 * 				    並可以在方法中使用關鍵字super呼叫父類的方法,這樣做即可以保有父類的功能,也可以擁有子類特有的功能
 *  方法重寫的注意事項:
 *  			  不能重寫父類私有的方法
 *  			 許可權必須大於等於父類方法的許可權
 *  
 *  註解:@
 *  
 */
public class ExtendsTest {
	public static void main(String[] args) {
		NewPhone np = new NewPhone();
		np.call();
	}
}

class Phone {
	void call() {
		System.out.println("打電話");
	}
}

class NewPhone extends Phone {

	@Override
	public void call() {
		System.out.println("錄音");
		// System.out.println("打電話");

		// super.call();
	}
}

1.7 繼承中構造方法的執行順序
A:super(實參列表);語句 在子類的構造方法中使用,用來呼叫父類中的構造方法(具體哪一個由傳遞的引數決定),並且只能在構造方法的第一行使用
B:this(實參列表); 語句 在類的構造方法中使用,用來呼叫本類中的其它構造方法(具體哪一個由傳遞的引數決定),並且只能在構造方法的第一行使用
1.7.1 案例程式碼七

package demo;

/*
 * 繼承中構造方法的執行順序
 * 			在子父類中,建立子類物件,呼叫子類的構造方法,
 * 			在子類的構造方法的第一行程式碼如果沒有呼叫父類的構造或者沒有呼叫子類的其他構造,則預設呼叫父類無參構造
 * 為什麼要呼叫父類構造?
 * 			因為需要給父類的成員變數初始化
 * 肯定會先把父類的構造執行完畢,在去執行子類構造中的其他程式碼
 * 
 * 我是父類無參構造 --- 我是子類有參構造 --- 我是子類無參構造
 */
public class ExtendsTest {
	public static void main(String[] args) {
		// Die d = new Die();
		Zi6 z = new Zi6();
	}
}

class Die6 {
	public Die6() {
		System.out.println("我是父類無參構造");
	}

	public Die6(int num) {
		System.out.println("我是父類有參構造");
	}
}

class Zi6 extends Die6 {
	public Zi6() {
		// super(1);
		// super();

		this(1);// 不會再呼叫父類的無參構造了

		System.out.println("我是子類無參構造");
	}

	public Zi6(int num) {
		// 會預設呼叫父類無參構造
		System.out.println("我是子類有參構造");
	}
}

1.8 this與super區別
1.8.1 案例程式碼八:

package demo;

/*
 * this和super的區別
		this:當前物件的引用
			呼叫子類的成員變數
			呼叫子類的成員方法
			在子類的構造方法第一行呼叫子類其他構造方法
		super:子類物件的父類引用
			呼叫父類的成員變數
			呼叫父類的成員方法
			在子類的構造方法第一行呼叫父類的構造方法
 */
public class ExtendsTest {
	public static void main(String[] args) {
		Zi z = new Zi();
		z.function();
	}
}

class Die {
	int num = 10;

	public Die() {
		System.out.println("我是父類無參構造");
	}

	public Die(int num) {
		System.out.println("我是父類有參構造");
	}

	public void method() {
		System.out.println("我是父類的方法");
	}
}

class Zi extends Die {
	// int num = 30;

	public Zi() {
		// this(1);//第一行不呼叫子類其他構造或者是父類構造,預設呼叫父類無參構造
		super();
		System.out.println("我是子類無參構造");
	}

	public Zi(int num) {
		System.out.println("我是子類有參構造");
	}

	public void method() {
		System.out.println("我是子類的方法");
	}

	public void function() {
		// this.num = 50;
		// System.out.println(num);
		// this.method();

		// super.num = 40;
		// super.method();

		System.out.println(this.num);
	}
}

1.9 繼承優缺點
A:優點
提高了程式碼的複用性
提高了程式碼的可維護性
B:缺點:
類的耦合性增強了
開發的原則:高內聚低耦合
內聚:就是自己完成某件事情的能力
耦合:類與類的關係