Java-多态(下)

简介: Java-多态(下)

4.向上转型和向下转型


     

7f09d2f597d04318b395012ec3a2cdda.png

      1. 向上转型:实际就是创建一个子类对象,将其当成父类对象来使用。

       语法格式:父类类型 对象名=new 子类类型()


Animal animal=new Dogs(“赛虎”,10);


        animal是父类类型,但可以引用一个子类对象,因为是从小范围向大范围的转换。


       向上转型方法:1直接赋值2.方法的参数,传参时向上赋值3.返回值向上转型。


       1.直接赋值


Animal animal=new Dogs(“赛虎”,10);


       2.方法的参数,传参时向上转型


//方法的参数,传参的时候向上转型
public static void func1(Animals animal) {
}
public static void main2(String[] args) {
    Dogs dog=new Dogs("赛虎",10);
    func1(dog);
}

e79b4746132c4474b42b49b18c118b61.png

        3.返回值向上转型


//3.返回值 向上转型
public static Animals main3(String[] args){
    Dogs dog=new Dogs("赛虎",10);
    return dog;
}

6d55b61e8fd24ce5b248efd8c100a920.png


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

     2. 向下转型:将一个子类对象经过向上转型之后当成父类方法使用,再无法调用子类的方法,但有时候可能需要调用子类特有的方法,此时:将父类引用再还原为子类对象即可


ee62ee136dce4c2493f7881d82130dfb.png


7474e47202834cb08fd61a0526e58923.png


Java中为了提高向下转型的安全性,引入了 instanceof ,如果该表达式为true,则可以安全转换。


public class Text {
        public static void main(String[] args) {
        //animal这个引用 指向了Dogs类的对象,向上转型直接赋值
        Animals animal=new Dogs("赛虎",10);
        animal.eat();//父类的eat
        System.out.println("====");
        //animal这个引用 指向了Cats类的对象,向上转型直接赋值
        animal=new Cats("菲菲",15);
        animal1.eat();
        //表示如果引用animal指向对象类型确实为Dogs对象实例
        if(animal instanceof Dogs){
                dog=(Dog)animal;
        }
        //表示如果引用animal指向对象类型确实为Cat对象实例
        if(animal instanceof Dogs){
                cat=(Cat)animal;
        }
    }
}


5.多态的优缺点



       若有以下代码

class Shape{
    public void drow(){
        System.out.println("画一个图案");
    }
}
//矩形
class Rect extends Shape{
    @Override
    public void drow() {
        System.out.println("矩形!~~~");
    }
}
//圆形
class Cycle extends Shape{
    @Override
    public void drow() {
        System.out.println("圆形⚪!~~~");
    }
}
//花形
class Flower extends Shape{
    @Override
    public void drow() {
        System.out.println("花形❀!~~~");
    }
}


       使用多态的好处:


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


               圈复杂度是一种描述一段代码复杂程度的方式. 一段代码如果平铺直叙, 那么就比较简单容易理解. 而如果有很多的条件分支或者循环语句, 就认为理解起来更复杂,我们可以简单粗暴的计算一段代码中条件语句和循环语句出现的个数, 这个个数就称为 "圈复杂度"。如果一个方法的圈复杂度太高, 就需要考虑重构。


       现在我们需要打印多个形状:


       不基于多态实现方法

public class Textshape {
        public static void main(String[] args) {
                Cycle cycle=new Cycle();
                Rect rect=new Rect();
                Flower flower=new Flower();
                String[] shapes={"cycle","rect","flower"}
                for(Sting shape:shapes){
                        if(shape.equals(''cycle")){
                                cycle.drow();
                        }
                       else if(shape.equals(''rect")){
                                rect.drow();
                        }
                        else if(shape.equals(''flower")){
                                flower.drow();
                        }
                }
}


       基于多态的实现方法

public class Textshape {
    public static void funshape(Shape shape){
        shape.drow();
    }
    public static void main(String[] args) {
        /*Shape shape1=new Cycle();  //直接赋值向上转型
        Shape shape2=new Rect();
        Shape shape3=new Flower();
        shape1.drow();
        shape2.drow();
        shape3.drow();*/
        /*Cycle cycle=new Cycle();
        Rect rect=new Rect();
        Flower flower=new Flower();
        funshape(cycle);  //方法传参向上转型
        funshape(rect);
        funshape(flower);*/
        //创建了Shape对象的数组
        Shape[] shapes={new Cycle(),new Rect(),new Flower()}
        for(Shape x:shapes){
                shape.drow();
        }
    }
}


d6e225a31d7e43d0ac6ad02d72283a3d.png


        2.可扩展能力强


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


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


       多态缺陷:代码的运行效率降低。

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

       2.构造方法没有多态性。


6.避免在构造方法中调用重写方法



       一段有坑的代码,创建两个类, B 是父类, D 是子类. D 中重写 func 方法. 并且在 B 的构造方法中调用 func。


class B{
        public B(){
                func();
        }
        public void func(){
                System.out.println("B.func()");
        }
}
class D extends B{
        private int num=1;
        @Override
        public void func() {
                System.out.println("D.func() " + num);
        }
}
public class Text {
    public static void main(String[] args) {
        D d = new D();
    }
}


c692c1f9bca84dc0b14fadabce1ead93.png

       构造 D 对象的同时, 会调用 B 的构造方法;B 的构造方法中调用了 func 方法, 此时会触发动态绑定, 会调用到 D 中的 func此时 D 对象自身还没有构造, 此时 num 处在未初始化的状态, 值为 0; 如果具备多态性,num的值应该是1;所以在构造函数内,尽量避免使用实例方法,除了final和private方法。

目录
相关文章
|
3月前
|
算法 Java 程序员
在Java的编程世界里,多态不仅仅是一种代码层面的技术,它是思想的碰撞,是程序员对现实世界复杂性的抽象映射,是对软件设计哲学的深刻领悟。
在Java的编程世界里,多态不仅仅是一种代码层面的技术,它是思想的碰撞,是程序员对现实世界复杂性的抽象映射,是对软件设计哲学的深刻领悟。
68 9
|
3月前
|
Java 开发者
在Java面向对象编程的广阔海洋中,多态犹如一股深邃的潜流,它推动着代码从单一走向多元,从僵化迈向灵活。
在Java面向对象编程的广阔海洋中,多态犹如一股深邃的潜流,它推动着代码从单一走向多元,从僵化迈向灵活。
42 7
|
3月前
|
Java 开发者
那些年,我们一同踏入Java编程的大门,多态,这个充满魔法的名字,曾无数次点亮我们探索面向对象编程的热情。
那些年,我们一同踏入Java编程的大门,多态,这个充满魔法的名字,曾无数次点亮我们探索面向对象编程的热情。
48 5
|
3月前
|
Java 程序员
让我们一起探讨Java多态的奥秘,看看它是如何打破“一刀切”的局限,让我们的代码更加生动多彩
让我们一起探讨Java多态的奥秘,看看它是如何打破“一刀切”的局限,让我们的代码更加生动多彩
42 5
|
3月前
|
Java 程序员
Java中的继承和多态:理解面向对象编程的核心概念
【8月更文挑战第22天】在Java的世界中,继承和多态不仅仅是编程技巧,它们是构建可维护、可扩展软件架构的基石。通过本文,我们将深入探讨这两个概念,并揭示它们如何共同作用于面向对象编程(OOP)的实践之中。你将了解继承如何简化代码重用,以及多态如何为程序提供灵活性和扩展性。让我们启程,探索Java语言中这些强大特性的秘密。
|
27天前
|
存储 Java 测试技术
Java零基础-多态详解
【10月更文挑战第10天】Java零基础教学篇,手把手实践教学!
20 4
|
1月前
|
Java 编译器 程序员
Java多态背后的秘密:动态绑定如何工作?
本文介绍了Java中多态的实现原理,通过动态绑定和虚拟方法表,使得父类引用可以调用子类的方法,增强了代码的灵活性和可维护性。文中通过具体示例详细解析了多态的工作机制。
35 4
|
2月前
|
Java 编译器
封装,继承,多态【Java面向对象知识回顾①】
本文回顾了Java面向对象编程的三大特性:封装、继承和多态。封装通过将数据和方法结合在类中并隐藏实现细节来保护对象状态,继承允许新类扩展现有类的功能,而多态则允许对象在不同情况下表现出不同的行为,这些特性共同提高了代码的复用性、扩展性和灵活性。
封装,继承,多态【Java面向对象知识回顾①】
|
1月前
|
Java
java继承和多态详解
java继承和多态详解
42 5
|
1月前
|
存储 Java 测试技术
Java零基础-多态详解
【10月更文挑战第1天】Java零基础教学篇,手把手实践教学!
26 1