一直觉得自己对访问权限和函数覆写还挺明白的,直到碰见下面这个情况:
有三个类Animal、Dog和Test;Animal和Test在一个包中,Dog在另一个包中;Dog继承了Animal;Animal和Dog中的bark()方法都是protected的。Test中生成一个Animal引用的Dog对象,调用bark()方法的打印结果是dog bark。
我的问题是Dog中的bark()方法不是protected的吗,这时候Test能成功调用Dog的bark()方法吗?package a;
class Animal {
  protected void bark(){
    System.out.println("animal bark");
}-------------------------------------package b;
import a.Animal;
class Dog extends Animal{
  protected void bark(){
    System.out.println("dog bark");
}---------------------------------------package a;
import b.Dog;
class Test {
  public static void main(String[] args) {
    Animal anim = new Dog();
    anim.bark();
  }
}

解决方案 »

  1.   

    因为bark()方法在父类中是protected的, 已经构成了运行时绑定, 也就是"多态"了.
      

  2.   

    我的问题是Dog中的bark()方法不是protected的吗,这时候Test能成功调用Dog的bark()方法吗?
    我不太明白  向上转型 动态绑定 多态  不是这样吗 为什么不能调用啊?能啊
      

  3.   

    Test不能成功调用Dog的bark()方法,
      

  4.   

    其实你在Test中只能动态的调用Dog中的bark()方法,无法再取用基类中的bark()方法,或者就在Dog中重新写一函数显式调用Animal中的bark()方法
      

  5.   

    anim.bark();这一句是可以运行的.在运行时根据实际anim对象的引用,就调用了Dog里边的方法了..
    但是如果
        Dog anim = new Dog();
        anim.bark();
    就会提示bark() has protected access in ...
      

  6.   

    多态如果是Dog anim则不能被调用
      

  7.   

    另外还有种情况,如果把Animal和Dog的bark()方法都改为默认权限的话,如下所示:package a;
    class Animal {
      void bark(){
        System.out.println("animal bark");
    }-------------------------------------package b;
    import a.Animal;
    class Dog extends Animal{
      void bark(){
        System.out.println("dog bark");
    }---------------------------------------package a;
    import b.Dog;
    class Test {
      public static void main(String[] args) {
        Animal anim = new Dog();
        anim.bark();
      }
    }
    这时候Test执行的结果就成了animal bark了,这又如何解释?
      

  8.   

    很好解释, 因为Dog虽然继承自Animal, 但因为处于不同的包, 所以并没有继承Animal的bark()方法, 所以Dog中的bark()并没有覆盖Animal中的bark(), 它们只是碰巧使用了相同的名字而已, 因而没有构成多态.
      

  9.   

    再补充一点就是:Animal anim = new Dog();这句中, 当Dog向上转型到Animal时, 丢失了原来的bark()方法, 所以这时anim.bark();就仅仅与Animal类相关了, 因为它不是一个多态的方法.
      

  10.   

    无论是protected还是默认权限,实际型别都是Dog吧,那么在访问bark()方法时为什么会有不同?能不能把protected和默认权限这两种情况结合起来解释一下,还是有点晕
      

  11.   

    建议楼主去看一下<Thinking in JAVA>中"多态"一章.举个例子, 我们都知道下面的代码的运行结果:public class Animal {  private void bark() { System.out.println("animal bark"); }  public static void main(String[] args) {
        Animal dog = new Dog();
        dog.bark();
      }}class Dog extends Animal {  void bark() { System.out.println("dog bark"); }}结果是"animal bark". 因为Animal中的bark()方法是private的, 所以虽然Dog中也有bark()方法, 但并不是继承自Animal. 我们可以把Dog中的bark()方法看成是另一个方法, 它和Animal中的bark()方法没有什么联系, 并未构成多态. 当将变量dog由Dog向上转型到Animal时, 由于原来的bark不是一个多态方法, 在父类Animal中找不到相应的父级版本, 所以它被屏蔽掉了(或者说丢失了). 所以这时dog.bark()实际上调用的是父类实例中的bark().楼主的例子和这个类似, 只不过范围扩大了一级, 由这里的private-default扩大到了default-protected, 但道理是一样的.
      

  12.   

    不是说java中函数调用都是根据对象的实际型别进行的吗?