首页 > 编程语言 >Javase-11.多态

Javase-11.多态

时间:2024-07-22 21:00:24浏览次数:16  
标签:11 name void 多态 public age Animal Javase eat

1.什么是多态?

多态的概念:通俗来说就是多种形态.具体点就是去完成某个行为时,不同的对象去完成会产生不同的状态.

比如:同样是打印,彩色打印机打印出来的纸是彩色的,而黑白打印机打印出来的是黑白色的.

多态体现:在代码运行时,当传递不同类对象时,会调用对应类中的方法。

2.多态实现的条件

在 java 中要实现多态,必须要满足如下几个条件,缺一不可: 1.在继承体系下 2.子类必须要重写父类中的非构造方法 3.通过父类的引用调用重写的方法
public class Animal {
    String name;
    int age;

    public Animal(String name,int age) {
        this.name = name;
        this.age = age;
    }

    public void eat() {
        System.out.println(name+ "吃饭");
    }

}

class Cat extends Animal {
    public Cat(String name, int age) {
        super(name, age);
    }

    @Override
    public void eat() {
        super.eat();
    }
}

class Dog extends Animal {
    public Dog(String name, int age) {
        super(name, age);
    }

    @Override
    public void eat() {
        super.eat();
    }
}


class Test {
    public static void eat(Animal a) {
        a.eat();
    }

    public static void main(String[] args) {
        Cat cat = new Cat("小猫",2);
        Dog dog = new Dog("小狗",3);

        eat(cat);
        eat(dog);
    }
}
输出结果:
小猫吃饭
小狗吃饭
在上述代码中 , 水平 线上方的代码是 类的实现者 编写的 , 水平 线下方的代码是 类的调用者 编写的 . 当类的调用者在编写 eat 这个方法的时候 , 参数类型为 Animal ( 父类 ), 此时在该方法内部并 不知道 , 也不关注 当前的 a 引用指向的是哪个类型 ( 哪个子类 ) 的实例 . 此时 a 这个引用调用 eat 方法可能会有多种不同的表现 , 这种行为就称为 多态 .

3.重写

重写 (override) :也称为覆盖。重写是子类对父类非静态、非 private 修饰,非 final 修饰,非构造方法等的实现过程进行重新编写, 返回值和形参都不能改变即外壳不变,核心重写! 重写的好处在于子类可以根据需要,定义特定于自己的行为。  方法重写的规则 1. 子类在重写父类的方法时,一般必须与父类方法原型一致: 返回值类型 方法名 ( 参数列表 ) 要完全一致 2. 被重写的方法返回值类型可以不同,但是必须是具有父子关系 3.  访问权限不能比父类中被重写的方法的访问权限更低。例如:如果父类方法被 public 修饰,则子类中重写该方 法就不能声明为 protected 4.  父类被 static 、 private 修饰的方法、构造方法都不能被重写 5.  重写的方法 , 可以使用 @Override 注解来显式指定 . 有了这个注解能帮我们进行一些合法性校验 . 例如不小心 将方法名字拼写错了 ( 比如写成 aet), 那么此时编译器就会发现父类中没有 aet 方法 , 就会编译报错 , 提示无法 构成重写 . 重写和重载的区别 重写的设计原则 对于已经投入使用的类,尽量不要进行修改。最好的方式是:重新定义一个新的类,来重复利用其中共性的内容,并且添加或者改动新的内容。 静态绑定 :也称为前期绑定 ( 早绑定 ) ,即在编译时,根据用户所传递实参类型就确定了具体调用那个方法。典型代表函数: 重载。 动态绑定 :也称为后期绑定 ( 晚绑定 ) ,即在编译时,不能确定方法的行为,需要等到程序运行时,才能够确定具体调用那个类的方法。

4.向上转型和向下转型

4.1向上转型

向上转型:就是创建一个子类对象,将其当成父类对象来使用。 语法格式:父类类型 对象名 = new 子类类型 ()
Animal animal = new Cat("小猫",2);
animal 是父类类型,但可以引用一个子类对象,因为是从小范围向大范围的转换。 使用方式: 1.直接赋值
Animal animal = new Cat("小猫",2);
2.方法传参
public static void eat(Animal a) {
    a.eat();
}
3.方法返回
public class Animal {
    String name;
    int age;

    public Animal(String name,int age) {
        this.name = name;
        this.age = age;
    }

    public void eat() {
        System.out.println(name+ "吃饭");
    }

}

class Cat extends Animal {
    public Cat(String name, int age) {
        super(name, age);
    }

    @Override
    public void eat() {
        super.eat();
    }
}

class Dog extends Animal {
    public Dog(String name, int age) {
        super(name, age);
    }

    @Override
    public void eat() {
        super.eat();
    }
}

class Test {
//方法传参
    public static void eat(Animal a) {
        a.eat();
    }
//方法返回值
    public  static Animal buyAnimal(String a) {
        if("狗".equals(a)) {
            return new Dog("小狗",2);
        }else if ("猫".equals(a)) {
            return new Cat("小猫",4);
        }else{
            return null;
        }
    }

    public static void main(String[] args) {
        //直接赋值
        //Animal animal = new Cat("小猫",2);
        Dog dog = new Dog("小狗",3);
        Cat cat = new Cat("小猫",5);

        //animal.eat();

        System.out.println("=====================");

        eat(dog);
        eat(cat);

        System.out.println("=====================");

        Animal animal = buyAnimal("狗");
        animal.eat();

        animal = buyAnimal("猫");
        animal.eat();

    }
}
向上转型的优点:让代码实现更简单灵活。 向上转型的缺陷:不能调用到子类特有的方法。

4.2向下转型

将一个子类对象经过向上转型之后当成父类方法使用,再无法调用子类的方法,但如果需要调用子类特有的方法,此时将父类引用再还原为子类对象即可,即向下转换。
public class Animal {
    String name;
    int age;

    public Animal(String name,int age) {
        this.name = name;
        this.age = age;
    }

    public void eat() {
        System.out.println(name+ "吃饭");
    }

}

class Cat extends Animal {
    public Cat(String name, int age) {
        super(name, age);
    }

    @Override
    public void eat() {
        super.eat();
    }
}

class Dog extends Animal {
    public Dog(String name, int age) {
        super(name, age);
    }

    @Override
    public void eat() {
        super.eat();
    }

    public void bark() {
        System.out.println("汪汪汪~~~");
    }

}

class Test {
    public static void eat(Animal a) {
        a.eat();
    }

    public  static Animal buyAnimal(String a) {
        if("狗".equals(a)) {
            return new Dog("小狗",2);
        }else if ("猫".equals(a)) {
            return new Cat("小猫",4);
        }else{
            return null;
        }
    }

    public static void main(String[] args) {
        Dog dog = new Dog("小狗",5);
        Cat cat = new Cat("小猫",1);

        Animal animal = dog;

        animal.eat();

        //程序报错,编译时编译器将animal当成Animal对象处理
        //而Animal类中没有bark方法,因此编译失败
        //animal.bark;

        System.out.println("=========");

//向下转型,animal实际指向的是狗,现在强制还原为猫,无法正常还原,
编译器报错:Exception in thread "main" java.lang.ClassCastException: com.Dog cannot be cast to com.Cat

        //cat = (Cat)animal;
       
//animal原本就是指向dog,因此将animal还原为dog不会报错.
         dog = (Dog)animal;
         dog.bark();
    }
}
向下转型用的比较少,而且不安全,万一转换失败,运行就会异常。 Java 中为了提高向下转型的安全性,引入了 instanceof ,如果该表达式为 true ,则可以安全转换。
if(animal instanceof Cat) {
    cat = (Cat)animal;
}

if(animal instanceof Dog) {
    dog = (Dog)animal;
}

5.多态的优缺点

优点:

1. 能够降低代码的 "圈复杂度", 避免使用大量的 if - else

什么叫 " 圈复杂度 " ? 圈复杂度是一种描述一段代码复杂程度的方式 . 一段代码如果平铺直叙 , 那么就比较简单容易理解 . 而如 果有很多的条件分支或者循环语句 , 就认为理解起来更复杂 . 因此我们可以简单粗暴的计算一段代码中条件语句和循环语句出现的个数 , 这个个数就称为 " 圈复杂度 ". 如果一个方法的圈复杂度太高 , 就需要考虑重构 . 不同公司对于代码的圈复杂度的规范不一样 . 一般不会超过  10 不使用多态时,我们将会怎么打印多个形状?
class Shape {
    public void draw() {
        System.out.println("画图");
    }
}

class Rect extends Shape {
    @Override
    public void draw() {
        System.out.println("⬜");
    }
}

class Cycle extends Shape {
    @Override
    public void draw() {
        System.out.println("⚪");
    }
}

class Flower extends Shape {
    @Override
    public void draw() {
        System.out.println("❀");
    }
}

class Test2 {
    public static void drawShapes() {
        Rect rect = new Rect();
        Cycle cycle = new Cycle();
        Flower flower = new Flower();
        String[] shapes = {"cycle","rect","cycle","rect","flower"};

        for(String shape : shapes) {
            if(shape.equals("cycle")) {
                cycle.draw();
            }else if (shape.equals("rect")) {
                rect.draw();
            }else{
                flower.draw();
            }
        }
    }

    public static void main(String[] args) {
        drawShapes();
    }

}

使用多态:

public static void main(String[] args) {
    // 创建一个 Shape 对象的数组.
    Shape[] shapes = {new Cycle(),new Rect(),new Cycle(),new Rect(),new Flower()};

    for(Shape shape : shapes) {
        shape.draw();
    }
}

2.可扩展能力更强

如果要新增一种新的形状, 使用多态的方式代码改动成本也比较低.

class Triangle extends Shape {
    @Override
    public void draw() {
        System.out.println("△");
    }
}

缺点:代码运行效率低.

1. 属性没有多态性 当父类和子类都有同名属性的时候,通过父类引用,只能引用父类自己的成员属性 2. 构造方法没有多态性

标签:11,name,void,多态,public,age,Animal,Javase,eat
From: https://blog.csdn.net/2302_81886858/article/details/140611638

相关文章

  • 实训day11(7.22)
    1、环境准备(1)yum源(一个云仓库+pepl仓库) [root@web~]#vim/etc/yum.repos.d/hh.repo  [a] name=a baseurl=file:///mnt gpgcheck=0 [root@web~]#vim/etc/fstab  /dev/cdrom/mntiso9660defaults00 [root@web~]#mount-a [root@web~]#yumrep......
  • 关于ssh的X11Forwarding功能和vnc端口冲突的问题
    前言偶然间发现有时vnc端口启动不了,显示端口已经启动,但是查看发现默认的59xx端口未启动,但是60xx端口缺被一个sshd进程占用,vnc服务除了默认的59xx端口,还会用到60xx端口。正是因为这个60xx端口被sshd进程占用,所以vnc才启动不了。 那么这个sshd端口是干嘛的呢,默认的sshd端口不是......
  • 踩坑记录:windows11下使用 VS2022 和 PCL1.14.1 配置点云开发环境
    闲话不多说,具体在windows下下载PCL与解压pcl可以看https://www.yuque.com/huangzhongqing/pcl/这位大佬的文章,那我就具体说一下踩过点坑:踩坑点1:按照大佬的文章的步骤进行解压与下载,我的PCL环境下在了K盘中,但是最后不知怎么的我的openni2文件夹下在了C盘里,也就是说3rdparty文件夹......
  • 鼠标宏设置实现智能定时抢购,双11薅羊毛必会技能
    双11快到了,你还在手动定时间抢购商品吗?今天给大家介绍使用金舟鼠标连点器内的鼠标宏“找图”功能实现电脑定时自动购物技巧。通过设置抢购时间的变量和高匹配度的图片查找。轻松实现电脑自动点击“立即抢购”和“提交订单”功能。轻松抢购优惠的商品。鼠标宏设置教程......
  • python面向对象三大特性(继承、多态、封装)之继承
    来吧,下面来具体说一下面向对象的三大特性:所谓封装、多态和继承。我们先来说一下继承。所谓继承,顾名思义,子类继承父类的属性,包括数据属性和函数属性。写个简单的例子吧:1.简单的继承classAnimal:need_substance='water'def__init__(self):print('这是一......
  • zig vs c++:控制x11鼠标移动
    zigDebug输出大小:2.3MBReleaseSmall输出大小:11.3kBconststd=@import("std");constx11=@cImport({@cInclude("X11/Xlib.h");});//Convertsbetweennumerictypes:.Enum,.Intand.Float.pubinlinefnas(comptimeT:type,from:anyty......
  • “点点通”餐饮点餐小程序-计算机毕业设计源码11264
    "点点通"餐饮点餐小程序XXX专业XX级XX班:XXX   指导教师:XXX摘要 随着中国经济的飞速增长,消费者的智能化水平不断提高,许多智能手机和相关的软件正在得到更多的关注和支持。其中,微信的餐饮点餐小程序更是深得消费者的喜爱,它的出现极大地改善了消费者的生活质量,同时,它还创......
  • SSM泰华超市商品管理系统-计算机毕业设计源码11946
    目 录摘要1绪论1.1研究背景1.2 研究意义1.3论文结构与章节安排2系统分析2.1可行性分析2.2系统流程分析2.2.1数据新增流程3.2.2 数据删除流程2.3 系统功能分析2.3.1功能性分析2.3.2非功能性分析2.4 系统用例分析2.5本章小结3 系......
  • SSM小说阅读网站-计算机毕业设计源码11362
    摘 要本文介绍了一个基于SSM框架和MySQL数据库的小说阅读网站的设计与实现。该网站旨在为用户提供一个方便、舒适的在线小说阅读平台。该小说阅读网站具有以下主要功能:用户注册与登录、小说分类浏览、小说搜索、阅读历史记录、小说畅听等。通过该网站,用户可以根据自己的兴......
  • Debian 11 上安装 postgresql
    1.增加官方的Repository手动配置官方的aptRepository#Importtherepositorysigningkey:$sudoaptinstallcurlca-certificates$sudoinstall-d/usr/share/postgresql-common/pgdg$sudocurl-o/usr/share/postgresql-common/pgdg/apt.postgresql.org.asc--fa......