使用对象类型引用调用函数(持有不同的实例)

时间:2016-08-03 10:48:00

标签: java object reference polymorphism

我将Dog类描述为:

class Dog {
//data members
void bark() {
   //Bark Algorithm
  }
}

现在在另一个具有main方法和main方法的类中,如果我执行以下操作:

Object dog = new Dog();
dog.bark();

不应该因为“狗”引用持有Dog实例而有效吗?为什么这无效?

这里使用的语言是Java。

感谢您的帮助。

4 个答案:

答案 0 :(得分:1)

Java的输入非常强。 Java编译器在编译时执行方法检查,而不是在运行时。 dog被声明为Object,因此编译器会检查Object类是否有名为bark()的方法。它没有,所以它抛出编译器错误。这就是Java的设计方式。

请注意,这不是多态本身的限制,而是Java中多态性实现的限制。这个完全相同的代码可以完全编译(并且工作)在更加动态类型的语言中,例如Groovy,它也可以在JVM上运行。

答案 1 :(得分:1)

类Object没有名为bark的方法。因此,您的代码将无法编译。

但是,这并不意味着编译器决定纯粹基于引用类型调用哪种方法。您的引用类型决定了您 CAN 调用的方法,而实例类型将决定您调用的方法。这是多态性的重要机制。

例如,

class Animal
{
    void makeSound()
    {
        //Generic animal sound algorithm
    }
}

class Dog extends Animal{
    void makeSound() 
    {
       //Bark Algorithm
    }
}

然后

Animal dog = new Dog();
Animal animal = new Animal();
dog.makeSound(); //calls bark
animal.makeSound(); //generic animal sound

答案 2 :(得分:0)

我想我在这里得到了解决方案。编译器根据引用类型决定调用哪个函数,而不是基于引用的实例类型。

就像在这种情况下一样,就像Dog类一样,许多其他动物也可以被实例化,并且可以使用Object引用来引用它们在堆上的对象,但并非所有动物都可以使用bark()。因此,编译器决定函数调用应该基于引用类型,而不是实例类型。

答案 3 :(得分:-2)

如果您确定dog的类型,您可以随时进行类型转换

Object dog = new Dog();
((Dog)dog).bark();

安全版:

Object dog = new Dog();
if (dog instanceof Dog) 
    ((Dog)dog).bark();

<强> UPD

多态性示例:

interface Animal {
}


interface Barkable extends Animal {
    void bark();
}

class Dog implements Barkable {
    @Override
    public void bark() {
        System.out.println("woof-woof");
    }
}

class Cat implements Barkable {
    @Override
    public void bark() {
        System.out.println("meow");
    }
}

class SilentCreature implements Animal {
}

....


Animal animal = new Dog();
animal.bark();

animal = new Cat();
animal.bark();

animal = new SilentCreature();  
// new SilentCreature() returns new animal, but not Barkable 
animal.bark(); // as Animal doesn't have method bark() this code won't compile