java中的方法天生具有繼承多態特性,這點與C++有很大不同(需要在父類方發上加virtual關鍵字),但用起來確實方便了許多。
最簡單的繼承多態
聲明一個接口BaseIF,只包含一個方法聲明
public interface BaseIF { void Access(); }
一個基類Base,基類實現了BaseIF接口,Access會調用Base類的public函數test()(實現類最好不要有自己的public函數,public函數應提到接口中,這里是為了說明問題方便)
public class Base implements BaseIF { public void Access(){ test(); } public void test(){ System.out.println("test in Base"); } }
一個派生類Derived,派生類重寫test(),並保持test()的訪問權限保持不變,依然為public
public class Derived extends Base { //@Override public void test(){ System.out.println("test in Derived"); } }
Demo入口測試代碼
public class Main { public static void main(String[] args) { BaseIF face = new Derived(); face.Access(); } }
代碼運行結果為:
表明實際調用的test()方法來自Derived類,這便是繼承多態的運行方式。
降低派生類中test方法的訪問權限
將Derived類中test()的訪問權限改為protect或者private,這時IDE會報編譯錯誤,子類重寫父類方法時,不可以降低方法的可訪問性。
public class Derived extends Base { @Override protected void test(){ System.out.println("test in Derived"); } }
這一點其實很好理解,將測試代碼寫成下面這樣。假如可以在Derived中降低test()的訪問權限,那么base.test()應該調用基類的test()方法還是Derived類的?
假如調用Base類的test(),那么子類重寫test()變沒有什么意義了;假如調用Derived類的,就會出現一個問題,Derived類的test()是protect方法,無法在類外部調用,假如通過基類可以調用派生類的protect或private方法,權限訪問控制變出現了漏洞,所以最好的處理方式就是禁止在派生類中降低重寫方法的可訪問性
public class Main { public static void main(String[] args) { Base base = new Derived(); base.test(); } }
提升派生類中test方法的訪問權限
將Base類中test()的訪問權限改為protect,將Derived類中test()的訪問權限改為public,這時程序可以正確執行,說明可以在派生類中提升test()方法的可訪問性。
public class Base implements BaseIF { public void Access(){ test(); } protected void test(){ System.out.println("test in Base"); } }
public class Derived extends Base { @Override public void test(){ System.out.println("test in Derived"); } }
但有一點需要注意的是,如果Base中test()為private,那么在Derived中是看不到Base的test()的。這時Derived中如果也添加test()方法(無論訪問權限是什么),都不屬於重寫Base的test()方法,Derived的test()方法只屬於Derived類本身,而這時也無法實現多態。舉例:
public class Base implements BaseIF { public void Access(){ test(); } private void test(){ System.out.println("test in Base"); } }
public class Derived extends Base { //@Override public void test(){ System.out.println("test in Derived"); } }
public class Main { public static void main(String[] args) { BaseIF face = new Derived(); face.Access(); } }
運行結果:
test in Base