欢迎光临
我们一直在努力

10分钟带你搞懂多态~

1.什么是多态

顾名思义,多态就是事物的多种形态。简单来说就是“同一个接口,不同的实现。”

  • 多态的表现形式:父类类型  对象名=new 子类类型();
  • 多态的前提:
  • 有继承/实现关系
  • 有父类引用指向子类对象

  • 2.多态的使用场景

    在学生管理系统中,我们会有学生类型,老师类型,管理员类型,在每个成员使用之前,都必须注册账号。

    //注册方法
    public boolean register(Student s){

    }

    在这里如果我们注册方法的形参是Student类型的话,那么同样也需要形参是Teacher、Administrator的方法,增加了代码的复用性,只有形参不同,而需要的注册功能是相同的,还得再写一个方法。那么我们可以利用多态来解决这种问题。

    例如:创建一个父类Person

    public class Person {
    private String name;//姓名
    private String username;//账号名
    private String password;//密码

    public Person() {
    }

    public Person(String name, String username, String password) {
    this.name = name;
    this.username = username;
    this.password = password;
    }

    public String getName() {
    return name;
    }

    public void setName(String name) {
    this.name = name;
    }

    public String getUsername() {
    return username;
    }

    public void setUsername(String username) {
    this.username = username;
    }

    public String getPassword() {
    return password;
    }

    public void setPassword(String password) {
    this.password = password;
    }

    }

    在创建子类:Student、Teacher

    public class Student extends Person {
    public Student(){
    super();
    }
    public Student (String name, String username, String password){
    super( name, username, password);
    }
    }

    public class Teacher extends Person {
    public Teacher(){
    super();
    }
    public Teacher(String name, String username, String password){
    super( name, username, password);
    }
    }

    测试类:Test

    public class Test {
    public static void main(String[] args) {
    Student s =new Student("张三","zhang","123456");
    Teacher t =new Teacher("李四","li","456789");
    //注意下面的register方法的形参是Person类型的,而我们这里穿过去的实参分别是Student、Teacher类型的
    register(s);
    register(t);
    }
    //注册方法
    public static void register(Person p){
    System.out.println("姓名是"+p.getName()+"注册成功账号是:"+p.getUsername()+",密码是:"+p.getPassword());
    }

    }

    输出结果:

    通过上面的例子,我们不难看出来利用父类Person作为register作为形参,可以接受子类的所有对象,这样我们解决了一开始的问题。

    方法的形参是父类,就可以接受子类所有的对象。


    3.多态调用成员的特点

    • 变量调用:编译看左边,运行也看左边。

    在java文件编译成class文件时,先看父类中有没有这个变量,如果有那就可以编译成功,反之,则不能。

    运行看左边:在代码最后的运行结果用的是父类当中的该变量,并非子类。

    • 方法调用:编译看左边,运行看右边。

    编译看左边:先看父类中有没有这个方法,如果有就编译成功,没有则失败。

    运行看左边:在代码真正用的是子类当中的方法。如果子类没有重写父类当中的方法,那就是用父类。

    变量调用例子:先了解变量编译看左边

    创建父类Person、子类Student

    public class Person {
    String name;
    }
    public class Student extends Person {
    String work="学习";
    }

    测试:Test

    public class Test {
    public static void main(String[] args) {
    Person p=new Student ();
    /*编译看左边:因为name是父类Person中的变量,所以下面p.name能够编译成功
    而s.name就不会编译成功,会显示红色报错。
    */
    String Name =p.name;
    String Name1 =s.name;//编译器在这里会高亮报错

    //同样Student 中特有的子类work也无法编译成功
    String work=s.work;
    }
    }

    变量运行也看左边:

    创建父类Person、子类Student

    public class Person {
    String name="张三";
    }
    public class Student extends Person {
    String name="李四";
    }

    测试:Test

    public class Test {
    public static void main(String[] args) {
    Person p=new Student ();
    System.out.println(p.name);
    }
    }

    输出结果:

    最后运行结果是父类中的name。

    多态方法调用的例子类似,可以自己尝试。


    4.多态的优缺点

    先说优点:

    • 优点
  • 方法中使用父类作为参数类型,可接受所有子类类型和父类类型(同一接口,不同实现)。
  • 如果方法重写,利用多态调用方法,可以不同子类中重写的方法。
  • 通过目录2中代码,我们已经可以看出优点1,接下来举个例子来体现优点2。

    例如:创建一个父类Person

    public class Person {
    public void work(){
    System.out.println("每个人都需要工作");
    }
    }

    子类Student、Teacher

    public class Student extends Person {
    @Override
    public void work(){
    System.out.println("学生的工作是学习");
    }
    }
    public class Teacher extends Person {
    @Override
    public void work(){
    System.out.println("老师的工作是教书");
    }
    }

    测试:Test

    public class Test {
    public static void main(String[] args) {
    Student s =new Student();
    Teacher t =new Teacher();
    s.work();
    t.work();
    }

    }

    输出结果:

    所以这个例子我们可以知道优点2。

    再了解过优点后,我们来看一下缺点。

    缺点:多态下不能使用子类特有的功能。

    此缺点下面会有破解方案

    例子:创建父类对象Person

    public class Person {
    public void work(){
    System.out.println("工作");
    }
    }

    子类Student、Teacher

    public class Student extends Person {
    public void study(){
    System.out.println("我要好好学习!!!");
    }
    }
    public class Teacher extends Person {
    public void teach(){
    System.out.println("教书育人");
    }
    }

    测试Test:

    public class Test {
    public static void main(String[] args) {
    Person p1=new Student ();
    Person p2=new Teacher();
    /*study、teach分别是子类p1、p2中特有的功能,由于他们的父类Person中没有,
    所以下面两行代码是会报错的!!!*/
    p1.sutdy;
    p2.teach;

    }
    }

    5.多态当中的类型转换

    • 自动类型转换(从子到父):又称为向上转型,子类对象自动转换为父类类型(小变大)。
    • 强制类型转换(从父到子):又称为向下转型,子类  对象变量=(子类)父类类型的变量

    格式例子:

    Person  p  =  new  Student();

    Student  s  =(Student)p;

    在目录4中了解到多态使用的缺点,我们可以通过强制类型转换来解决这个问题:

    父类、子类与目录4当中缺点的一致,只有Test类不同。

    测试Test:

    public class Test {
    public static void main(String[] args) {
    Person p1=new Student ();
    Person p2=new Teacher();

    Student s=(Student)p1;
    Teacher t=(Teacher) p2;
    s.study();
    t.teach();
    }
    }

    输出结果:

    不难看出再通过强制类型转换后,我们可以使用子类当中特有的功能。

    注意:

    间接父类  爷爷 直接父类  爸爸 子类  儿子

    我们在创建爸爸的对象,赋值给了爷爷类型。代码:Ye  ye  = new  Ba();

    再进行强制转换时,只能将爷爷强转到爸爸类型,不能转成儿子类型。

    6.instanceof关键字

    所以接下来我们引入instanceof关键字,用于判断多态中是否能进行强转。

    public class Test {
    public static void main(String[] args) {
    // 创建爸爸对象,赋值给爷爷类型
    Ye ye = new Ba();

    // 使用instanceof判断能否转换
    if (ye instanceof Ba) {
    System.out.println("可以转成爸爸类型");
    Ba ba = (Ba) ye; // 强制转换
    ba.work(); // 调用爸爸特有方法
    }

    if (ye instanceof Er) {
    System.out.println("可以转成儿子类型");
    Er er = (Er) ye;
    er.play();
    } else {
    System.out.println("不能转成儿子类型");
    }
    }
    }

    // 爷爷类
    class Ye {
    public void speak() {
    System.out.println("爷爷");
    }
    }

    // 爸爸类
    class Ba extends Ye {
    public void work() {
    System.out.println("爸爸在工作");
    }
    }

    // 儿子类
    class Er extends Ba {
    public void play() {
    System.out.println("儿子在玩耍");
    }
    }

    输出结果:


    回到开头的注册系统,正是因为用了多态,我们只写了一个 register(Person p) 方法,就能处理所有类型的人员注册。如果不用多态,Student、Teacher、Admin 各写一个方法,代码会臃肿成什么样?这只是一个小例子,在日常开发中我们也会用很多使用多态的场景。

    希望可以帮助你理解多态。

    赞(0)
    未经允许不得转载:171主机测评 » 10分钟带你搞懂多态~
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址