Java继承,重写方法时改变方法的访问权限

  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();
    }
}

  代码运行结果为:

Java继承,重写方法时改变方法的访问权限

  表明实际调用的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