多态
多态是同一个行为具有多个不同表现形式或形态的能力。
多态就是同一个接口,使用不同的实例而执行不同操作,如图所示:
多态的实现方式
方式一:重写:
方式二:接口
方式三:抽象类和抽象方法
实际上方式二、方式三基于的都是方式一的方法重写以及我们的向上造型机制,这里我们不再详细论述,仅以代码简单表示
public class Demo {
public static void main(String[] args) {
/*向上造型*/
Animal animal = new Cat();
Animal animal2 = new Horse();
animal.eat();
animal2.eat();
/*向下转型(强制类型转换)*/
Cat cat = (Cat) animal;
Horse horse = (Horse) animal;//java.lang.ClassCastException
}
}
class Animal{
String name;
String age;
public Animal() {}
public Animal(String name) {
super();
this.name = name;
}
public void eat() {
System.out.println("动物吃东西");
}
public void sleep() {
System.out.println("动物睡觉");
}
}
class Cat extends Animal{
public void eat() {
System.out.println("猫吃鱼为生");
}
public void sleep() {
System.out.println("猫趴着睡觉");
}
}
class Horse extends Animal{
public void eat() {
System.out.println("马吃草为生");
}
public void sleep() {
System.out.println("马站着睡觉");
}
}
运行结果:
猫吃鱼为生
马吃草为生
注意:之所以向下转型会出现ClassCastException
- 向下转型能够实现的关键在于
——被转型的子类对象必须要是转型目标类型的实例或是它的子类实例
成员的多态(重写)问题
- 成员方法:
这个不做过多论述,正如上面的例子,
Animal animal = new Cat();
Animal animal2 = new Horse();
animal.eat();//猫吃鱼
animal2.eat();//马吃草
最终animal和animal2同样是执行名为eat的方法,执行的eat一定是他们重写后的eat方法
- 成员变量:
class Animal{
String name = "动物";
public Animal() {}
public Animal(String name) {
super();
this.name = name;
}
public void getname() {
System.out.println(this.name);
}
}
class Cat extends Animal{
String name;
public Cat() {}
public Cat(String name) {
this.name = name;
}
public void getname() {
System.out.println(this.name);
}
}
public class Demo {
public static void main(String[] args) {
Animal animal = new Cat("猫");
Cat cat = (Cat) animal;
System.out.println("父类引用:"+animal.name);
System.out.println("子类引用:"+cat.name);
System.out.print("父类引用调用方法:");
animal.getname();
}
}
输出结果:
父类引用:动物
子类引用:猫
父类引用调用方法:猫
- 注意:
我们发现:animal.name和animal.getname()输出的结果居然不一样?这个例子也就正说明了:当成员变量在父子类中重名的时候,实际上两个name都是存在的,并没有发生替代(重写),只有借用重写方法中this.name才能输出Animal引用的Cat对象中的name,这是因为java中,向上造型呈现的多态性仅仅针对成员函数,成员属性不具有多态性