面向对象的特性之(三)——多态

1. 多态的前提

  1. 类与类的继承:extends
  2. 类与接口的实现:implements
  3. 接口与接口的继承:extends

2. 什么是多态

  • 一个对象拥有多种形态,就是多态。
    如:一个人的多级继承关系:小明->学生->人->生物;
    此时,小明显然具有多种形态,既是学生,又是人,还是生物。
    同理,接口的实现,接口的继承,也同样会产生多态性。
  • 代码中的多态:父类引用指向子类对象
    格式:
    父类名 对象名=new 子类名();
    接口名 对象名=new 实现类名();
    //显然,学生也是人,子类就是一个父类。
    

3. 访问成员变量

1.直接通过对象名访问成员变量
看等号左边是谁,就是谁的成员变量,没有才向上找
编译看左边,运行也看左边

package linxu.day08;
public class fu {
    int num=30;
}

package linxu.day08;
public class zi extends fu{
    int num=50;
}

package linxu.day08;
public class maindemo {
    public static void main(String[] args) {
        fu obj=new zi();
        System.out.println(obj.num);//30,obj这个对象,等号左边是fu类,所以是fu类的num
    }

}
  1. 间接通过成员方法访问成员变量
    看该方法属于谁,优先用谁,没有则向上找
    编译看左边,运行看右边
    本质上是对成员方法的访问
    即看该对象new的是谁
package linxu.day08;
public class fu {
    int num=30;
    public void showNum(){
        System.out.println(num);
    }
}

package linxu.day08;
public class zi extends fu{
    int num=50;
    public void showNum(){
        System.out.println(num);
    }
}

package linxu.day08;
public class maindemo {
    public static void main(String[] args) {
        fu obj=new zi();
    	obj.showNum();//obj是zi类new的对象,因此showNum优先查找zi类方法
    }

}

4. 访问成员方法

在多态的代码中,成员方法的访问:
new的是谁,优先用谁,没有则向上找
编译看左边,运行看右边

package linxu.day08;
public class fu {
	public void mathodfu(){System.out.println("父类方法");}
	public void mathod(){System.out.println("公共方法——父类");}
}

package linxu.day08;
public class zi extends fu{
   public void mathodzi(){System.out.println("子类方法");}
   public void mathod(){System.out.println("公共方法——子类");}
}

package linxu.day08;
public class maindemo {
    public static void main(String[] args) {
        fu obj=new zi();
    	obj.mothod();//公共方法——子类,编译时看左边,是fu obj,fu类有mothod;运行看右边是new zi(),zi类也有mothod方法,优先使用子类方法
    	obj.mothodfu();//父类方法,编译时看左边,是fu obj,fu类有mothodfu;运行看右边是new zi(),zi类没有mothodfu方法,向上找
    	obj.mothodzi();//错误写法;编译时看左边,是fu obj,而fu类没有mothodzi,所以报错
    }

}

5.为什么要用多态

在这里插入图片描述
通过上图,我们可以知道,既然左边的类型统一了,那么,我们能做的就很多了,

  • 比如,只需要一个ArrayList的数组,其中可以同时存放不同子类的对象。
  • 可以通过重写父类抽象方法实现每一个子类不同的方法。
  • 甚至在传参时,只需要使用父类作为参数类型,所有子类对象都可以传入,不需要写多个重载的函数

示例如下:

package linxu.day08;
public abstract class Employee {
    String name;
    public abstract void show();
}

package linxu.day08;
public class teacher extends Employee{
    String name;
    public teacher(String name) {
        this.name = name;
    }
    @Override
    public void show() {
        System.out.println(name);
    }
}

package linxu.day08;
public class assistant extends Employee{
    String name;
    int age;
    public assistant(String name, int num) {
        this.name = name;
        this.age = num;
    }
    @Override
    public void show() {
        System.out.println(name+" "+age);
    }
}

package linxu.day08;
import java.util.ArrayList;
public class maindemo {
    public static void main(String[] args) {
        ArrayList<Employee> list =new ArrayList<Employee>();
        Employee one=new teacher("李老师");
        list.add(one);
        Employee two=new assistant("王助教",19);
        list.add(two);
        //俩个teacher、assistant类的对象,通过多态巧妙的放入了一个数组。
        list.get(0).show();// one.show();//李老师
        list.get(1).show();//two.show();//王助教 19
        System.out.println("-------------------");
        showHHH(list,0);// one.show();//李老师
        showHHH(list,1);// one.show();//王助教 19
    }
    public static void showHHH(ArrayList<Employee> list,int i){
        list.get(i).show();
    }
    //只一个函数,便同时实现了传入不同类型数据的功能,既可以传入Employee类,
    //也可以是teacher、assistant类
}

这个示例同时介绍了抽象方法、ArrayList、多态、继承等概念的综合使用。

  • 不管Employee还会派生多少子类,绝大部分方法都不需要有任何改动。为软件的升级和维护提供了极大的便利。
  • 接口和父类作用相同,都可以作为参数,这里的Employee也可以写成接口,不一定非得是父类

6. 对象的向上转型

其实就是多态的写法。
格式:父类名 对象名 = new 子类名();
含义:右侧创建一个子类对象,把它当作父类对象来看待
向上转型一定是安全的(小范围->大范围)。
弊端:一旦向上转型,就没办法调用子类特有方法。
解决方案:向下转型

7. 对象的向下转型

对象的向下转型,就是一个还原的过程。
格式:子类名 对象名 = (子类名)父类对象;
含义:将父类对象,还原为原本的子类对象。
此时就可以调用子类特有方法。
向下转型不一定安全,绝对不能向下转型成为其他的子类,否则在运行时会发生类转化异常(ClassCastException)

在这里插入图片描述

8. instanceof关键字

  • 怎么知道一个父类引用的对象,本来是什么子类呢?
    当需要使用子类特有方法,就需要向下转型,但如何判断转型是否正确?
    使用instanceof关键字。
  • 格式:对象名 instanceof 类名这将得到一个bollean值,判断前面对象是否可以当作后面的类来使用。
  • 例如:
    if(one instanceof teacher) {
                teacher tea1 = (teacher) one;
                System.out.println("one的子类是teacher");
                tea1.show();
            }
    if(two instanceof teacher) {
         teacher tea2 = (teacher) two;
         System.out.println("two的子类是teacher");
         tea2.show();
     }
     /*打印结果:
       one的子类是teacher
    	李老师
     */
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值