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