我将Dog类描述为:
class Dog {
//data members
void bark() {
//Bark Algorithm
}
}
现在在另一个具有main方法和main方法的类中,如果我执行以下操作:
Object dog = new Dog();
dog.bark();
不应该因为“狗”引用持有Dog实例而有效吗?为什么这无效?
这里使用的语言是Java。
感谢您的帮助。
答案 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