12.多态
多态:事物存在的多种体现形态
例:动物中猫,狗。
- 猫这个对象对应的类型是猫类型:猫 x=new 猫();
- 同时猫也是动物中的一种,也可以把猫称为动物:动物 y=new 猫();
动物是猫和狗具体事物中抽取出来的父类型。
父类型引用指向了子类对象
体现:父类的引用指向了自己的子类对象;父类的引用也可以接受自己的子类对象。
作用:提高了程序的扩展性
应用前提:
- 需要存在继承或实现关系;
- 需要有重写操作。
例1
public class MulitDemo {
public static void main(String[] args){
Animal c = new Cat();
method(c);
method(new Dog());
method(new Pig());
}
public static void method(Animal a){
a.eat();
}
}
abstract class Animal{
public abstract void eat();
}
class Cat extends Animal{
public void eat(){
System.out.println("吃鱼");
}
public void catchMouse(){
System.out.println("抓老鼠");
}
}
class Dog extends Animal{
public void eat() {
System.out.println("吃骨头");
}
public void watchDoor(){
System.out.println("看家");
}
}
class Pig extends Animal{
public void eat() {
System.out.println("吃饲料");
}
public void gongdi(){
System.out.println("拱地");
}
}
运行结果:
例2
class MulitDemo2{
public static void main(String[] args){
Animal a = new Cat();//类型提升,向上转型
a.eat();
//如果想要调用猫的特有方法时,
//强制将父类的引用转成子类类型,向下装换
Cat c =(Cat)a;
c.catchMouse();
//不能出现将父类对象转成子类类型的操作;
//多态始终都是子类对象在做变化
//Animal a = new Animal();
//Cat c = (Cat)a;
//Animal a = new Dog();
//Cat c = (Cat)a;//也不能随意转换,
//否则可能回报出ClasCastException的异常
}
public static void method(Animal a){
a.eat();
if(a instanceof Cat){
Cat c = (Cat) a;
c.catchMouse();
}
else if(a instanceof Dog){
Dog d = (Dog) a;
d.watchDoor();
}
}
}
例3
public class MutilDemo3 {
public static void main(String[] args) {
DoSth ds = new DoSth();
ds.doSomething(new BaseStudent());
}
}
class DoSth{
public void doSomething(Student st){
st.sleep();
st.study();
}
}
abstract class Student{
public abstract void study();
public void sleep(){
System.out.println("躺着睡");
}
}
class BaseStudent extends Student{
public void study(){
System.out.println("base study");
}
public void sleep(){
System.out.println("坐着睡");
}
}
class AdvStudent extends Student{
public void study(){
System.out.println("avd sleep");
}
}
运行结果:
12.1 在多态中成员函数(非静态)的特点:
- 在编译时期,参考引用型变量所属的类中是否有调用的方法,如果有,编译通过,如果没有编译失败;
- 在运行时期,参考对象所属的类中是否有调用的方法;
简单说,成员函数在多态调用时,编译看左边,运行看右边。
class Fu1{ void method1(){ System.out.println("fu_method_1"); } void method2(){ System.out.println("fu_method_2"); } } class Zi1 extends Fu1{ void method1(){ System.out.println("zi_method_1"); } void method3(){ System.out.println("zi method_3"); } } public class MutilDemo3 { public static void main(String[] args){ Fu1 f = new Zi1(); f.method1(); f.method2(); //f.method3(); } }
运行结果为:
12.2 在多态中成员变量的特点:
- 编译时,参考引用型变量所属的类中是否有调用的成员变量,如果有则编译通过,没有则编译失败;
- 运行时,参考引用型变量所属的类是否有调用的成员变量,并运行该所属类中的成员变量;
- 无论编译和运行,都参考左边(引用类型变量所属的类);
12.3 在多态中静态成员、函数的特点:
无论编译和运行,都参考左边(引用类型变量所属的类);
class Fu1{ int num = 5; void method1(){ System.out.println("fu_method_1"); } void method2(){ System.out.println("fu_method_2"); } static void method4(){ System.out.println("fu_method_4"); } } class Zi1 extends Fu1{ int num = 6; void method1(){ System.out.println("zi_method_1"); } void method3(){ System.out.println("zi method_3"); } static void method4(){ System.out.println("zi method_4"); } } public class MutilDemo3 { public static void main(String[] args){ Fu1 f= new Zi1(); System.out.println(f.num); f.method4(); Zi1 z= new Zi1(); System.out.println(z.num); z.method4(); } }
运行结果: