JAVASE语法零基础——多态

Java系列文章目录


在这里插入图片描述

Write once,Runanywhere.🔥🔥🔥

💥 💥 💥如果你觉得我的文章有帮助到你,还请【关注➕点赞➕收藏】,得到你们支持就是我最大的动力!!!
💥 💥 💥

版权声明:本文由【马上回来了】原创、在CSDN首发、需要转载请联系博主。
版权声明:本文为CSDN博主「马上回来了」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

在这里插入图片描述

🚀🚀🚀 新的知识开始喽🚀🚀🚀
在这里插入图片描述



1.多态

多态的概念:通俗来说,就是多种形态,具体点就是去完成某个行为,当不同的对象去完成时会产生出不同的状态。
比如让中国人和外国人写作文,在不是特殊的情况下,中国人用中文写,外国人用外文写。

2.实现多态的三个条件

2.1 向上转型

向上转型:父类引用引用子类的对象。
三种向上转型:
1.直接引用型(核心)
直接通过引用实现向上转型

//父类引用 引用了 子类的对象
        Animal animal1 = new Cat("小橘",2);

2.传参数型
通过传递参数实现向上转型

public class Test {
                        // 父类引用
    public static void fun(Animal animal){
        animal.eat();
    }
    public static void main(String[] args) {
           //子类对象
        fun(new Cat("小黑",1));
        fun(new Dog("白虎",1));

    }

3.返回值类型
通过返回值构成父子类的关系实现向上转型

 //      返回值类型 父类
    public static Animal funcc(){
        // 返回子类对象
        return new Cat("122",1);
    }

完成向上转型后,父类的引用引用了子类的对象,无法在访问子类的属性和方法,只能引用父类的方法和属性。但是如果父类的方法被重写了,那么父类引用会调用子类这个被重写的方法。

2.2 方法重写

方法重写:
1.方法名、返回值类型、参数表(参数类型、个数、顺序)都一样。
2.被static、private、final修饰的方法不能再被重写。
3.子类重写方法的修饰限定符对于等于父类的修饰限定符
4.返回值类型如果不一样,则必须是父子类型。
在这里插入图片描述

class Animal{
    private String name;
    private int age;


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

    public String getName() {

        return name;
    }

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

    public int getAge() {

        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
    public void eat(){
        System.out.println(name+"正在吃饭"+"(Animal)");
//        return new Animal("121",121);
    }

    @Override
    public String toString() {
        return "Animal{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
class Cat extends Animal{
    public String catpaw;

    public Cat(String name, int age) {
        super(name, age);
    }
    public void miaomiao(){
        System.out.println(getName()+"正在喵喵喵");
    }
    @Override
    /**
     * 1.方法名、参数(类型、个数、顺序)、返回值一样
     * 2.被static、private、final修饰的方法名不能重写
     * 3.子类的修饰符访问权限大于等于父类
     * 4.如果返回值不相同,那么返回值类型必须构成父子关系
     */
    public void eat(){
        System.out.println(getName()+"正在吃猫粮");
//        return new Cat("1551",1);
    }
}

2.3 动态绑定

动态绑定:通过父类的引用调用这个被重写的方法。
在编译时父类还是引用的父类自己未被重写的方法,在运行时,父类引用发生动态绑定,引用由调用父类未被重写的方法变成调用被重写的方法。
在这里插入图片描述

在这里插入图片描述

class Animal{
    private String name;
    private int age;


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

    public String getName() {

        return name;
    }

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

    public int getAge() {

        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
    public void eat(){
        System.out.println(name+"正在吃饭"+"(Animal)");
//        return new Animal("121",121);
    }

    @Override
    public String toString() {
        return "Animal{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
class Dog extends Animal{

    public Dog(String name, int age) {
        super(name, age);
    }
    public void bark(){
        System.out.println(getName()+"正在汪汪汪");
    }

    @Override
    public void eat() {
        System.out.println(getName()+"正在吃狗粮");
    }
}
class Cat extends Animal{
    public String catpaw;

    public Cat(String name, int age) {
        super(name, age);
    }
    public void miaomiao(){
        System.out.println(getName()+"正在喵喵喵");
    }
    @Override
    /**
     * 1.方法名、参数(类型、个数、顺序)、返回值一样
     * 2.被static、private、final修饰的方法名不能重写
     * 3.子类的修饰符访问权限大于等于父类
     * 4.如果返回值不相同,那么返回值类型必须构成父子关系
     */
    public void eat(){
        System.out.println(getName()+"正在吃猫粮");
//        return new Cat("1551",1);
    }
}
public class Test {
    public static void fun(Animal animal){
        animal.eat();
    }
    //      返回值类型 父类
    public static Animal funcc(){
        // 返回子类对象
        return new Cat("122",1);
    }
    public static void main(String[] args) {
        fun(new Cat("小黑",1));
        fun(new Dog("白虎",1));

    }

运行结果:

总结:多态是一种思想,通过父类引用去引用子类对象,通过父类引用去调用这个被重写的方法,此时发生了动态绑定,父类的引用只有这一个,该引用所引用子类对象的不同,通过调用同一个方法所表现的结果不同。

int a = 10;
int b = 20;
a + b;
a>b;

3.向下转型

将一个子类对象经过向上转型之后当成父类方法使用,再无法调用子类的方法,但有时候可能需要调用子类特有的方法,此时:将父类引用再还原为子类对象即可,即向下转换。
向下转型用到关键字instanceof
能够向下转型:
在这里插入图片描述
不能够向下转型:
在这里插入图片描述
在这里插入图片描述

class Animal{
    private String name;
    private int age;


    public Animal(String name, int age) {
        this.name = name;
        this.age = age;
        eat();// 父类 构造方法里调用的方法也能实现动态绑定 但是以后不要这样写代码 除非考试考
    }

    public String getName() {

        return name;
    }

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

    public int getAge() {

        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
    public void eat(){
        System.out.println(name+"正在吃饭"+"(Animal)");
//        return new Animal("121",121);
    }

    @Override
    public String toString() {
        return "Animal{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
class Dog extends Animal{

    public Dog(String name, int age) {
        super(name, age);
    }
    public void bark(){
        System.out.println(getName()+"正在汪汪汪");
    }

    @Override
    public void eat() {
        System.out.println(getName()+"正在吃狗粮");
    }
}
class Cat extends Animal{
    public String catpaw;

    public Cat(String name, int age) {
        super(name, age);
    }
    public void miaomiao(){
        System.out.println(getName()+"正在喵喵喵");
    }
    public void Ninelives(){
        System.out.println("猫有九条命");
    }
    @Override
    /**
     * 1.方法名、参数(类型、个数、顺序)、返回值一样
     * 2.被static、private、final修饰的方法名不能重写
     * 3.子类的修饰符访问权限大于等于父类
     * 4.如果返回值不相同,那么返回值类型必须构成父子关系
     */
    public void eat(){
        System.out.println(getName()+"正在吃猫粮");
//        return new Cat("1551",1);
    }
}
 public static void main6(String[] args) {
        Animal animal = new Dog("白虎",2);
      //通过instanceof来判断 如果结果为true则执行向下转型
        if ( animal instanceof Cat){
            //不是所有的动物都是猫 狗子不是猫
            Cat cat =(Cat) animal;
            cat.Ninelives();
        }

    }
    public static void main5(String[] args) {
        Animal animal = new Cat("小橘",1);
        //向下转型
       if (animal instanceof Cat){
           Cat cat =(Cat) animal;
           cat.Ninelives();
       }

    }
 }

4.避免在父类构造方法中调用被子类重写的方法

结论: “用尽量简单的方式使对象进入可工作状态”, 尽量不要在构造器中调用方法(如果这个方法被子类重写, 就会触发动态绑定, 但是此时子类对象还没构造完成), 可能会出现一些隐藏的但是又极难发现的问题。
在这里插入图片描述

class Animal{
    private String name;
    private int age;


    public Animal(String name, int age) {
        this.name = name;
        this.age = age;
        eat();// 父类 构造方法里调用的方法也能实现动态绑定 但是以后不要这样写代码 除非考试考
    }

    public String getName() {

        return name;
    }

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

    public int getAge() {

        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
    public void eat(){
        System.out.println(name+"正在吃饭"+"(Animal)");
//        return new Animal("121",121);
    }

    @Override
    public String toString() {
        return "Animal{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
class Dog extends Animal{

    public Dog(String name, int age) {
        super(name, age);
    }
    public void bark(){
        System.out.println(getName()+"正在汪汪汪");
    }

    @Override
    public void eat() {
        System.out.println(getName()+"正在吃狗粮");
    }
}
public class Test {
    public static void main(String[] args) {
        Animal animal = new Animal("动物",1);
        Dog dog = new Dog("狗子",2);

    }
 }

 

运行结果:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

5.多态的优缺点

先看下面的代码:

class Shape{
    public void draw(){
        System.out.println("画图形");
    }
}
class Thefireworks extends Shape{
    @Override
    public void draw() {
        System.out.println("🎇");
    }
}
class Smile extends Shape{
    @Override
    public void draw() {
        System.out.println("😊");
    }
}
class Flower extends Shape{
    @Override
    public void draw() {
        System.out.println("💐");
    }
}
public class ShapeTest {
    public static void drawMap(Shape shape){
        shape.draw();

    }
    public static void main(String[] args) {
        Thefireworks thefireworks = new Thefireworks();
        Smile smile = new Smile();
        Flower flower = new Flower();
        drawMap(thefireworks);
        drawMap(smile);
        drawMap(flower);

    }
}

用数组:

class Shape{
    public void draw(){
        System.out.println("画图形");
    }
}
class Thefireworks extends Shape{
    @Override
    public void draw() {
        System.out.println("🎇");
    }
}
class Smile extends Shape{
    @Override
    public void draw() {
        System.out.println("😊");
    }
}
class Flower extends Shape{
    @Override
    public void draw() {
        System.out.println("💐");
    }
}
public class ShapeTest {
    public static void drawMap(Shape shape){
        shape.draw();

    }
    public static void main(String[] args) {
        Thefireworks thefireworks = new Thefireworks();
        Smile smile = new Smile();
        Flower flower = new Flower();
        //向上转型
        Shape [] shapes = {thefireworks,smile,flower,thefireworks,smile,flower};
        for (Shape shape:shapes){
            shape.draw();
        }
//        drawMap(thefireworks);
//        drawMap(smile);
//        drawMap(flower);

    }
}

如果这段代码不用多态实现:

class Shape{
    public void draw(){
        System.out.println("画图形");
    }
}
class Thefireworks extends Shape{
    @Override
    public void draw() {
        System.out.println("🎇");
    }
}
class Smile extends Shape{
    @Override
    public void draw() {
        System.out.println("😊");
    }
}
class Flower extends Shape{
    @Override
    public void draw() {
        System.out.println("💐");
    }
}
public class ShapeTest {
    public static void drawMap(Shape shape) {
        shape.draw();

    }

    public static void main(String[] args) {
        Thefireworks thefireworks = new Thefireworks();
        Smile smile = new Smile();
        Flower flower = new Flower();
        String[] shapes = {"thefireworks", "smile", "flower", "thefireworks", "smile", "flower"};
        for (String shape : shapes) {
            if (shape.equals("thefireworks")) {
                thefireworks.draw();
            } else if (shape.equals("smile")) {
                smile.draw();
            } else if (shape.equals("flower")) {
                flower.draw();
            } else if (shape.equals("thefireworks")) {
                thefireworks.draw();
            } else if (shape.equals("smile")) {
                smile.draw();
            } else if (shape.equals("flower")) {
                flower.draw();
            }
//        drawMap(thefireworks);
//        drawMap(smile);
//        drawMap(flower);

        }
    }
}

【使用多态的好处】

  1. 能够降低代码的 “圈复杂度”, 避免使用大量的 if - else什么叫 “圈复杂度” ?
    圈复杂度是一种描述一段代码复杂程度的方式. 一段代码如果平铺直叙, 那么就比较简单容易理解. 而如果有很多的条件分支或者循环语句, 就认为理解起来更复杂.
    因此我们可以简单粗暴的计算一段代码中条件语句和循环语句出现的个数, 这个个数就称为 “圈复杂度”.如果一个方法的圈复杂度太高, 就需要考虑重构.
    不同公司对于代码的圈复杂度的规范不一样. 一般不会超过 10 .
  2. 可扩展能力更强
    如果要新增一种新的形状, 使用多态的方式代码改动成本也比较低.

在这里插入图片描述
只用添加一段子类的代码。
对于类的调用者来说(drawShapes方法), 只要创建一个新类的实例就可以了, 改动成本很低.
而对于不用多态的情况, 就要把 drawShapes 中的 if - else 进行一定的修改, 改动成本更高.
多态缺陷:代码的运行效率降低


🌏🌏🌏今天的你看懂这里又学到了很多东西吧🌏🌏🌏

在这里插入图片描述

🌔 🌔 🌔下次见喽🌔 🌔 🌔
在这里插入图片描述

评论 19
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

马上回来了

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值