多态:父类类型的引用指向子类对象,也就是把子类对象看作父类类型(因为类就是一种数据类型)
同一个行为具有多个不同表现形式或形态的能力 多态就是同一个接口,使用不同的实例而执行不同操作,如图所示:
1. 三个必要条件:继承(实现) 重写 父类引用指向子类对象
2. 多态的弊端:多态对象只能调用父类中定义的方法,不能调用子类独立定义的方法,否则编译报错(找不到方法)
3. 优点:通常都是方法的参数使用多态,可以接受父类所有子类类型的对象,节省了很多函数的定义
如以下代码实例:使用多态实现子类对重写方法 eat() 方法的调用
abstract class Animal{ //父类定义为抽象类
public abstract void eat(); // 父类中的抽象方法
}
class Dog extends Animal{ // 定义子类狗类继承父类
public void eat(){ //子类重写父类的抽象方法并实现
Sysrem.out.println("狗吃骨头");
}
public void work(){ // 子类定义自己的方法
System.out.println("看家");
}
}
class AnimalTest{
public static void main(String[] args){
Dog dog=new Dog();//创建子类对象
dog.work(); //子类对象调用自己的方法
Animal gou=new Dog(); //以父类类型创建子类对象
gou.eat(); //子类对象调用父类的方法 执行子类重写并实现的方法
gou.work(); //编译出错:找不到符号gou.work() 因为work()方法是子类独有的,父类中没有此方法
}
}
多态中父类类型使用子类特有动能:
向上转型 (自动转换) 父类类型的引用指向子类对象,即以父类类型创建子类对象 。 如: Animal gou=new Dog();
向下转型(强制转换) 将父类类型的引用 gou 强制转换为子类 Dog 类型,以便调用子类独特的方法。 如:Dog dog=(Dog)gou; 相当于数据类型之间的转换 即 int j; byte i=(byte)(j+10);
instanceof 的作用:判断对象具体是什么类型
为了更好理解在多态中父类调用子类特有动能,下面附上代码实例:
abstract class Animal{ //父类定义为抽象类
public abstract void eat();
}
class Dog extends Animal{ // 定义子类狗类继承父类
public void eat(){
System.out.println("狗吃骨头");
}
public void work(){
System.out.println("狗看家");
}
}
class Cat extends Animal{
public void eat(){
System.out.println("猫吃鱼");
}
public void work(){
System.out.println("猫抓耗子");
}
}
class AnimalTest{
public static void main(String[] args){
Animal gou=new Dog(); //向上转型
Dog dog=(Dog)gou; //向下转型
show(dog);
Animal mao=new Cat();
Cat cat=(Cat)mao;
show(cat);
}
public static void show(Animal dongwu){
dongwu.eat(); // 子类共有的方法,也是父类中定义的方法,直接用父类类型指向的对象调用
if(dongwu instanceof Dog){ //判断对象的具体类型 即 Dog 型的 dongwu
Dog dog=(Dog)dongwu;
dog.work();
}
if(dongwu instanceof Cat){ // Cat 型的 dongwu
Cat cat=(Cat)dongwu;
cat.work();
}
}
}
4.多态中成员的特点:
成员变量的特点:
编译时要看父类,若调用父类没有的成员变量编译是无法通过的;运行结果也看父类,父类是什么值就打印什么值。
非静态成员方法的特点:
编译时看父类,若子类对象调用父类没有的成员方法编译是无法通过的;执行子类重写之后的成员方法,子类方法的表现形式是什么就打印什么。
静态成员方法的特点: 编译运行均看父类,父类有此静态方法才能调用。
子类在重写父类的方法时,如果父类方法的返回值是引用类型,子类的方法可以与父类的返回值类型一致,也可以是父类方法返回值类型的子类类型。
多态同样适用于接口。一个方法的参数类型可以试试接口类型,返回值类型可以是接口类型