java继承和重写概念的困难

java继承和重写概念的困难,java,inheritance,overriding,Java,Inheritance,Overriding,超类引用变量可以保存子类对象,但使用该变量只能访问超类的成员,因此要访问两个类的成员,建议始终为子类创建引用变量 class Animal { public void move() { System.out.println("Animals can move"); } } class Dog extends Animal { public void move() { System.out.println("Dogs can walk and run")

超类引用变量可以保存子类对象,但使用该变量只能访问超类的成员,因此要访问两个类的成员,建议始终为子类创建引用变量

class Animal {
   public void move() {
      System.out.println("Animals can move");
   }
}

class Dog extends Animal {
   public void move() {
      System.out.println("Dogs can walk and run");
   }
   public void bark() {
      System.out.println("Dogs can bark");
   }
}

public class TestDog {

   public static void main(String args[]) {
      Animal a = new Animal();   // Animal reference and object
      Animal b = new Dog();   // Animal reference but Dog object

      a.move();   // runs the method in Animal class
      b.move();   // runs the method in Dog class
      b.bark();
   }
}
输出:

TestDog.java:26: error: cannot find symbol
  b.bark();
   ^
symbol:   method bark()
location: variable b of type Animal
1 error

这里我不明白的是,为什么对象“b”能够访问Dog.move()而不是Dog.bark(),因为上面提到的语句说它只能访问超类的成员,不能访问子类。按照这个逻辑,b.move()的输出应该是“动物可以移动”,而不是“狗可以行走和奔跑”.但事实并非如此。有人能帮我吗?提前谢谢

祝贺您-您刚刚发现多态性


在Java中,类是动态绑定的。也就是说,如果您正在调用一个方法,那么将调用对象的实现(在您的示例中是
),而不是引用类型的方法(在您的示例中是
动物

这允许覆盖方法并替换或实现它们的实现



另一方面,您只能访问引用的类型中可用的方法,而不能访问实现类型(在您的示例中是
动物
)。要调用实例的方法,您必须将其用作引用类型(在您的示例中是
Dog
)。

此代码是错误的,因为行
b.bark()
将给您一个编译器错误,因为b只定义为动物,不能叫()

如果您更改
动物b=新狗()
狗d=新狗()它将正常工作

你把继承权搞混了。狗能做动物能做的事,反之亦然

class Animal {
    public void move() {
        System.out.println("Animals can move");
    }
}



class Dog extends Animal {
    @Override public void move() {
        System.out.println("Dogs can walk and run");
    }
    public void bark() {
        System.out.println("Dogs can bark");
    }
    public void moveSuper() {
        super.move();
    }
}



public class TestDog {

    public static void main(final String args[]) {
        final Animal a = new Animal(); // Animal reference and object
        a.move(); // runs the method in Animal class

        final Dog d = new Dog(); // Animal reference but Dog object
        d.move(); // runs the method in Dog class
        d.bark();
        d.moveSuper();
    }
}

这不会编译,因为
Animal
没有名为
bark
的方法


这样想吧,所有的狗都是动物,但并非所有的动物都是狗。所有的狗都会吠叫,但不是所有的动物都会吠叫。

在您的问题中
Animal
是一个没有
bark()
方法的父类,因此该方法不会被重写。如果您能够从父类访问
bark()
,而不声明抽象方法或定义它,那么这将违反原则

如果您确实希望以这种方式访问它,那么您可以定义一个
抽象的public void bark()或通过如下类型转换访问该方法

((Dog) b).bark();

知道了!谢谢@Fabian Damken.b.bark();这是错误的,因为动物不叫。需要向下浇铸,如:((狗)b).树皮();