多态概述:同一个对象,在不同时刻表现出来的不同形态。
举例:猫,我们可以说“猫是猫”,我们也可以说“猫是动物”。
这里猫在不同时刻表现出了不同形态,这就是多态。
多态的前提与体现
- 有继承/实现关系。
- 有方法重写。
- 有父类引用指向子类对象。(我们研究的是对象,所以最后关注的是子类对象)
这是Animal类,成员变量为age,成员方法为eat
public class Animal{
public int age=40;
public void eat(){
System.out.println("animal eats things");
}
}
这是Cat类,成员变量为age和weight,成员方法为eat和playGame
public class Cat extends Animal{
public int age=20;
public int weight=10;
public void eat(){
System.out.println("cat eats fish");
}
public void playGame(){
System.out.println("cat plays");
}
}
下面是一个Demo,用父类声明子类。
public class AnimalDemo {
public static void main(String[] args){
Animal a=new Cat();
System.out.println(a.age);
// System.out.println(a.weight);
a.eat();
//a.playGame();
}
}
我们会发现,Demo中注释的句子有误,原因是编译的时候,只有父类的变量和方法才能编译成功,由于父类没有weight的成员变量和playGame的成员方法,所以会提示你出错。
但最后结果,你会发现是:40 cat eats fish
说明输出的是父类的成员变量和子类的方法!
故多态中成员访问的特点如下:
- 对于成员变量:只编译父类有的,只输出父类的成员变量。
- 对于成员方法:只编译父类有的,输出的是子类的成员变量。
多态的好处与弊端(建议看视频多态部分p03)
public void useAnimal(Animal a){
//Animal a=new Cat();
//Animal a=new Dog();
a.eat();
}
假如有如上的方法,当括号内传入一个对象时,可以调用不同的子类方法。
多态的好处:提高了程序的扩展性,具体体现为,定义方法的时候,使用父类型作为参数,将来在使用时,使用具体的子类型参与操作。
多态的弊端:不能使用子类的特有功能。(这个很重要!!)
多态中的转型
- 向上转型,从子到父,父类引用指向子类对象
- 向下转型,从父到子,分类引用转为子类对象
public class AnimalDemo {
public static void main(String[] args){
Animal a=new Cat();
a.eat();
Cat c=(Cat)a;
c.eat();
c.playGame();
}
}
由上述代码可知,前一部分为向上转型,猫变动物,只能使用eat。
后一部分为向下转型,把动物a转成了猫c,能使用特有的playGame了。
案例:猫和狗(动态版)
public class Animal {
private String name;
private int age;
public Animal(){
}
public Animal(String name,int age){
this.name=name;
this.age=age;
}
public void setName(String name){
this.name=name;
}
public String getName(){
return name;
}
public void setAge(int age){
this.age=age;
}
public int getAge(){
return age;
}
public void eat(){
System.out.println("animal eats");
}
}
public class Cat extends Animal{
public Cat(){
}
public Cat(String name,int age){
super(name,age);
}
public void eat(){
System.out.println("cat eats");
}
}
public class Dog extends Animal{
public Dog(){
}
public Dog(String name,int age){
super(name,age);
}
public void eat(){
System.out.println("dog eats");
}
}
public class AnimalDemo {
public static void main(String[] args){
Animal a=new Cat();
a.setName("coffe");
a.setAge(5);
System.out.println(a.getName()+","+a.getAge());
a.eat();
a=new Cat("god",4);
System.out.println(a.getName()+","+a.getAge());
a.eat();
}
}
注意子类带参构造方法要使用super