複用類
介紹了繼承的知識,個人認爲繼承的核心是:導出類對象包含一個基類對象,就像是他的一個成員一樣,可以發送給基類對象的消息一樣可以發送給導出類對象,可以認爲導出類是基類的一個子集,一個類只能繼承一個基類。
多態
再來談談兩個很重要的概念:
向上轉型:如同上述所言,導出類是基類的子集,所以可以明確的說,導出類一定是一個基類,基類的聲明可以指向一個導出類的對象。
向下轉型:要理解這個蓋簾就要知道什麼叫運行時綁定,個人以爲這是理解向下轉型的核心思想;加入有一個基類A有一個方法F(),另有一個類B繼承了這個基類A,成爲了他的導出類,並重寫了基類的F()方法,有如下代碼:
public class A{
public void f(){
System.out.println("A");
}
}
class B extends A{
public void f(){
System.out.println("B");
}
}
class Test{
public static void main(String[] args){
A a = new B();
a.f();
}
}
可以很輕鬆的知道最終打印的結果是 B
這裏把一個導出類B的對象指向了基類,但是它並沒有喪失其在基類基礎上新定義的內容,當執行到a.f()時,爲甚麼會打印出
B而不是A,這就是運行時綁定的內容了,所以纔有了向下轉型。
接口
接口中只進行方法的聲明,而沒有具體的定義,且默認是public類型;接口中的變量是final類型的常量。實現一個接口必須實現接口的所有方法,一個類可以實現多個接口,這解決了多繼承問題。
關於接口的學習有一個關鍵詞 "接口回調" ,從效果上來看與繼承結構的向上、向下轉型是相差不大的:
可以把所有實現了某個接口的類都向上轉型爲接口類型,這也是運行時綁定參與的內容,定義時是實現了接口的類向 "接口類型"的向上轉型,當使用該對象調用某個方法時,就時通過運行時綁定進行的向下轉型了。
interface Basic{
void f();
int do(int a,int b);
}
class Test{
public static void main(String[] args){
List<Basic> basic = new ArrayList<>();
basic.add(new A());
basic.add(new A());
basic.add(new B());
basic.add(new B());
basic.add(new C());
for(int i=0;i<basic.size();i++){
if(i%2==0)
basic.get(i).f();
else
basic.get(i).do(i*2,i*3);
}
}
}
class A implements Basic{
public void f(){
System.our.println("A");
}
public int do(int a,int b){
return a + b * 2;
}
}
class A implements Basic{
public void f(){
System.our.println("B");
}
public int do(int a,int b){
return (a+b*10)/2;
}
}
class C implements Basic{
public void f(){
System.our.println("C");
}
public int do(int a,int b){
return Math.pow(a,b);
}
}
當然還可以用接口完成更具代表性的案例:例如工廠模式。
內部類
內部類是對多重繼承的補充,一個外部類可以包含多個內部類,每個內部類都可以繼承自某個接口或者某個基類,使用內部類進行多繼承的操作,相對於直接使用外部類進行多繼承的優點是更強的靈活性,內部類給我的感覺是即用即定義,用完即走;但是當通過外部類事項多繼承時:最直觀的感受是,當一個外部類實現了多個接口時,那麼這個類必定需要定義大量的方法,從閱讀代碼上來講也不夠順暢;但是將這個外部類實現的多個接口拆分開來,對於每個接口都使用一個內部類去實現它呢?我自認爲這樣會有更好的結構;