天天看點

小白第一步|Java繼承與多态的相關知識總結

作為一個資深的菜雞,既然稍微弄通了一點點的繼承多态

那當然要寫個部落格裝一下咯吼吼吼吼吼

首先溫習一下繼承的概念:子類可以繼承父類的公有屬性和方法并進行重寫

public class a extends b{
}
           

重點1:super和this的使用小解

那麼自然而然會想到一個十分哲學的問題:

我想用我父親的方法該怎麼用:

答案是:super函數!

下面簡單介紹一下super函數的一個用法:

super函數是唯一一個可以顯式調用父類方法:

①構造方法鍊:構造方法可以調用重載的構造方法。如果父類和子類的構造方法都沒有被顯式的調用,那麼編譯器就會自動地将super()作為構造方法的第一句。

public className(){
	//some statements
}
           

等價于

public className(){
	super();
	//some statements
}
           

②調用父類方法:super.方法名(參數)

this函數指向類中的屬性,也可以指向構造方法;

super和this函數綜合

例如:

public class a extends b{
    public static void main(String[] args) {
    	new a();
	}
    public a(){
    	System.out.print("invoke a");
    }
}

class b extends c{
	public b(){
		this.b("invoke b");
	}
	public b(String s){
		System.out.print(s);
	}
}

class c{
	public c(){
		System.out.print("invoke c");
	}
}
           

以上程式相當于

public class a extends b{
    public static void main(String[] args) {
    	new a();
	}
    public a(){
    	//b的super函數
    	super();
    	System.out.print("invoke a");
    }
}

class b extends c{
	public b(){
		//有this的顯式調用,不加super函數
		this.b("invoke b");
	}
	public b(String s){
		//c的super函數
		super();
		System.out.print(s);
	}
}

class c{
	public c(){
		System.out.print("invoke c");
	}
}
           

調用順序即為

a()super → b()this → b()super → c()

重點2:方法重寫

方法頭不變,方法體可以改寫,改寫過後可以用super通路父類的未改寫的方法;

區分方法重寫和方法重載

//方法重寫:不改變方法頭
public class a {
	public String toString(){A;}
}
public class b extends a{
	public String toString(){B;}
}

//方法重載,參數清單改變
public void A(double a){}
public void A(int a){}
           

重點3:多态

概念:每個可以調用父類執行個體的地方都能調用子類;

Object o = new GeometricObject();
System.out.print(o.toString());
           

上程式中o調用的是GeometricObject的方法

為什麼呢?

上程式中的解釋應該是這樣的:

建立一個Object類型的引用,指向GeometricObject類型的執行個體

那也就是:o類型是Object,指向GeometricObject類的執行個體

這樣就會引到動态綁定的問題:

動态綁定工作機制:

假設對象o是類C1,C2,……,Cn-1,Cn的執行個體,其中C1是C2的子類,C2是C3的子類……Cn是Cn-1的子類,那麼就有一個繼承串

C1→C2→C3→……→Cn-1→Cn

那麼假如o想調用一個方法p,那麼JVM會依次在C1,C2……查找方法p,一旦找到并實作後不再繼續查找;

例如:

public class Test{
	public static void main(String[] args) {
		new Person().printPerson;
		new Student().printPerson;
	}
}
    	
class Student extends Person{
	public String getInfo(){
		return "Student";
	}
}
class Person{
	public String getInfo(){
		return "Person";
	}
	public void printPerson(){
		System.out.println(getInfo);
	}
}
           

這個程式的傳回是

Person

Student

對第二個的解釋:

new Studen().printPerson();

定義後,JVM開始從Student深挖,Student中沒有該方法,則調用Person中的該方法,在調用printPerson方法是又需要調用getInfo函數,從Student開始找,在Student中找到,return并輸出,程式完成。

對象轉換規則和Instanceof函數

對象轉換規則:适用于多态的實作

方法:

小轉大直接轉,大轉小強制轉

如:

Object o = new Student();
Student b = (Student)o;
           

(注意轉型的文法,比較像資料類型的強制轉型)

既然o已經是Student的執行個體了,為什麼還要強制轉型?

解釋:

小轉大直接轉的原因是小的總會是大的的子類,是以Student的對象始終也是Object的執行個體

而大轉小時,Object中的執行個體不一定是Student的執行個體,是以需要強制轉型規定範圍;

instanceof函數:判斷子類是不是父類的子類

如:

A instanceof B :判斷A是不是B的執行個體,是的話傳回true,否的話傳回false;

而子類的執行個體也是父類的執行個體

是以

A instanceof B傳回true

public class A extends C{}

C instanceof B也傳回true

暫時到這