多态对象实例表现是什么
在面向对象编程中,多态是三大特性之一。它让同一个方法调用,在不同对象上能产生不同的行为。而“多态对象实例表现”就是指:当一个父类引用指向子类对象时,实际执行的是哪个类的方法。
举个生活中的例子,就像遥控器(父类)可以控制不同品牌的电视(子类)。你按下“开机”键,索尼电视启动的是索尼的开机画面,三星电视则显示自己的界面。遥控器不关心具体实现,但结果各不相同——这就是多态的表现。
代码中的多态实例
假设我们有一个动物类 Animal,它有个叫 makeSound 的方法。狗和猫都继承自 Animal,但叫声不一样:
class Animal {
public void makeSound() {
System.out.println("Animal makes a sound");
}
}
class Dog extends Animal {
@Override
public void makeSound() {
System.out.println("Woof! Woof!");
}
}
class Cat extends Animal {
@Override
public void makeSound() {
System.out.println("Meow~");
}
}当我们用父类类型来引用子类对象时:
Animal myPet1 = new Dog();
Animal myPet2 = new Cat();
myPet1.makeSound(); // 输出:Woof! Woof!
myPet2.makeSound(); // 输出:Meow~虽然变量类型是 Animal,但实际调用的是各自重写后的方法。这种运行时才确定具体行为的机制,正是多态的核心。
动态绑定与方法重写
多态对象实例表现依赖于方法重写(override)和动态绑定。编译阶段看的是引用类型,运行阶段看的是实际创建的对象类型。
比如下面这段代码:
Animal animal = Math.random() > 0.5 ? new Dog() : new Cat();
animal.makeSound();你无法在编译时知道 animal 到底是 Dog 还是 Cat,但程序照样能正确调用对应的声音方法。这就是动态绑定的魅力——把决策推迟到运行时刻。
接口也能实现多态
除了继承,接口也是实现多态的重要方式。例如定义一个 Playable 接口:
interface Playable {
void play();
}
class Piano implements Playable {
public void play() {
System.out.println("Piano music: Do Re Mi");
}
}
class Flute implements Playable {
public void play() {
System.out.println("Flute music: Suu suu");
}
}然后这样使用:
Playable instrument = new Piano();
instrument.play(); // 输出钢琴声
instrument = new Flute();
instrument.play(); // 输出笛子声同一个 play() 调用,根据背后实例的不同展现出不同的效果。这在开发插件系统、游戏角色技能等场景中非常实用。
常见误区提醒
注意,并非所有方法都能体现多态。只有被重写的方法才会表现出多态性。如果子类新增了一个父类没有的方法,通过父类引用来访问就会报错。
例如:
class Dog extends Animal {
public void bark() {
System.out.println("Dog is barking alone");
}
}
Animal dogRef = new Dog();
dogRef.bark(); // 编译错误!Animal 没有 bark 方法要调用 bark(),必须强制转为 Dog 类型,或者直接用 Dog 类型声明引用。