Java物件導向四大特性_繼承 ——戀天小結

2020-08-09 10:13:51

概念

繼承是從已有的類中派生出新的類,新的類能吸收已有類的屬性和行爲,並能擴充套件新的屬性和行爲。

Java繼承特點

1)Java是單繼承的,不支援多繼承。這樣使得Java的繼承關係很簡單,一個類只能有一個父類別,易於管理程式。同時一個類可以實現多個接 口,從而克服單繼承的缺點。

java 中只支援單繼承,並且是鏈式繼承(爹不能再繼承兒子)

2)繼承關係是傳遞的

3)private修飾的成員變數或方法是不能被繼承的

解決什麼問題

提高了程式碼的效率,避免了程式碼重寫

繼承的目的

程式碼複用

語法格式

[修飾符] class 子類 extends 父類別{
//類體
}

public static void main(String[] args){
	Cat c = new Cat();
	Dog d = new Dog();
	Bird b = new Bird();
	eat(c);
	//輸出結果爲 貓吃魚
	eat(d);
	//輸出結果爲  狗吃肉
	eat(b);
	//輸出結果爲 動物吃東西
}

//建立一個動物類 ,作爲父類別
class Animals{
	public void eat(){
		Systeam.out.println("動物吃東西");
	}
}

//建立一個貓類繼承動物類,作爲子類
class Cat extends Animal{
	public void eat() {
		System.out.println("貓吃魚");
	}
}
//建立一個狗類繼承動物類,作爲子類
class Dog extends Animal{
	public void eat() {
		System.out.println("狗吃肉");
	}
}
//建立一個鳥類繼承動物類,作爲子類
class Bird extends Animal{	
}

上面的程式碼中,cat,dog,bird都繼承了父類別動物類,
cat和dog類進行了覆寫 所以輸出的是子類的覆寫內容,這個後面會提到
bird類繼承了動物類,繼承了父類別的屬性,沒有進行重寫,所以輸出的是父類別輸出的內容

java中的根類 : Object
如果一個類沒有顯示繼承其他類,那麼該類預設繼承 java.lang.Object

Super

儲存了父類別型特徵,可以理解爲是父類別的物件參照(錯的)

語法
super(參數);
必須在子類構造方法的第一行
如果 子類構造方法中 沒有出現 this(xxx) 和 super(xxx)的話 會預設有一個super() 去呼叫父類別的無參構造
this(xxx) 這種寫法必須出現在構造方法第一行,所以 this(xxx) 和 super(xxx) 不能同時出現
this和super都不能出現在靜態上下文中

用法
1 用在子類成員方法,可以區分子類和父類同名的成員變數/成員方法
2 用在子類構造方法,同上
3 用在子類構造 方法中,用於呼叫父類別構造方法

public class Super_01 {
	Super_01(){
		//不寫,預設會有super()呼叫父類別無參構造
		super();
		System.out.println("子類構造方法");
	}
	int i = 2;
	

	public static void main(String[] args) {
		Super_01 s = new Super_01();
		s.m1();

	}
	public void m1() {
		//子類
		System.out.println("i");
		//父類別
		System.out.println("super.i");
		//子類
		System.out.println("this.i");
	}

}
class A{
	A(){
		super();
		System.out.println("父類別構造方法");
		
	}
	int i = 10;
}
如果構造方法私有化,就不能再有其他類繼承該類
	 因爲子類想要範例化物件,必須在構造方法中,呼叫父類別的構造方法
	   如果父類別構造方法私有化,那麼子類呼叫不到,報錯
public class Super_02 {
	public Super_02() {
		super();
	}

}
class B{
	//private B() {}
	public B() {}
}

構造方法可以和靜態方法/成員方法重名嗎?
靜態方法/成員方法的方法名可以和類名相同嗎?
可以

如何區分?
看返回值,構造方法 沒有返回值,連void都沒有

public static void main(String[] args) {
		new Super_03();

	}
	//成員方法
	public void Super_03(){
		System.out.println("1111111111法");
	}
	//構造方法
	public Super_03(){
	System.out.println("22222222222");
	}
package _08_Super;

public class Super_04 {

	public static void main(String[] args) {
		new Sub();

	}

}
class Sub extends Sup{
	{
		System.out.println("子類範例程式碼段1");
	}
	static {
		System.out.println("子類靜態程式碼段1");
	}
	Sub(){
		//super();
		this(2);
		//---------
		System.out.println("子類構造方法");
		
	}
	Sub(int i){
		super();
	}
}
class Sup{
	static {
		System.out.println("父類別靜態程式碼段1");
	}
	{
		System.out.println("父類別範例程式碼段1");
	}
	Sup(){
		super();
		//--------
		System.out.println("父類別構造方法");
	}
}

Override(重寫,覆寫)

繼承之後 子類必須和父類別一模一樣嗎?
不需要

概念
1 子類有特有的屬性,比如 父類別只有m1 , 子類中 還有 m2 ,這個m2 就是子類特有,父類別沒有

2 子類和父類別擁有相同名字的方法,但是功能不一樣,叫覆寫/重寫/覆蓋

覆寫 特指成員方法,和其他屬性無關

什麼時候需要進行覆寫?
當父類別方法無法滿足子類的業務需求時,需要對父類別方法進行覆寫
前提條件
1 必須有繼承關係的體系中
2 不能比原方法有更低的存取許可權 >=
3 錯誤不能越來越多,不能有更寬泛的異常 <=
4 方法名,返回值,參數列表 都必須一致
方法名不一致,說明是倆方法
參數列表不一致,是方法過載
返回值表示方法的功能,必須一樣,不能更改方法的本質

繼承的目的
程式碼重用

繼承最重要的功能
方法覆寫

重寫的意義
功能越來越強
使用範圍越來越廣
錯誤越來越少

用之前繼承舉例的程式碼來解釋

public static void main(String[] args){
	Cat c = new Cat();
	Dog d = new Dog();
	Bird b = new Bird();
	eat(c);
	//輸出結果爲 貓吃魚
	eat(d);
	//輸出結果爲  狗吃肉
	eat(b);
	//輸出結果爲 動物吃東西
}

//建立一個動物類 ,作爲父類別
class Animals{
	public void eat(){
		Systeam.out.println("動物吃東西");
	}
}

//建立一個貓類繼承動物類,作爲子類
class Cat extends Animal{
	//方法覆寫,重寫了父類別的eat()方法,輸出爲子類覆寫內容
	public void eat() {
		System.out.println("貓吃魚");
	}
}
//建立一個狗類繼承動物類,作爲子類
class Dog extends Animal{
	//方法覆寫,重寫了父類別的eat()方法,輸出爲子類覆寫內容
	public void eat() {
		System.out.println("狗吃肉");
	}
}
//建立一個鳥類繼承動物類,作爲子類
class Bird extends Animal{	
//未進行方法的覆寫,所以繼承父類別的屬性,輸出父類別的內容
}

Final

被Final修飾的
類 : 不能被繼承
成員方法 : 不能被覆寫
修飾的變數 : 不能二次賦值,並且沒有預設值,在整個程式的生命週期中,值不能被改變

常數
整個程式生命週期中,值不會被更改 / 使用final修飾的變數就是常數, 字面量也是常數

分類
靜態常數:(final修飾的靜態變數,一般是public static final ,由於是公共的,和物件沒有關係,所以應用較多)
所以 一般我們把 final修飾的靜態變數 叫常數
成員常數
區域性常數
命名規則 建議 全大寫,在eclipse中 使用 藍色、斜體 、 加粗 顯示

public class Final_01 {
	public static final int C = 2;
	final int i =2;
	final int a;
	//final修飾的變數沒有預設值,必須顯示賦值
	Final_01(int i){
		a = i;
	}
	

	public static void main(String[] args) {
		Final_01 f = new Final_01(2);
		//final修飾的變數不能被更改
		//f.i = 3;
		System.out.println(123);

	}

}
//final class A{
class A{
	//修飾的成員方法不能被覆寫
//	public final void m1() {
		
	//}
}
class B extends A{
	//class B{
         public void m1() {}	

}