通过向上向下转型对多态进行理解


2022-09-30-14:25:49

多态的基础语法

学习多态基础语法之前,两个概念:

    📧第一个:向上转型(通用语)

    子 --->父(自动类型转换)

    📧第二个:向下转型(通用语)

    父 --->子(强制类型转换,需要加强制类型转换符)

    注意:

      java中允许向上转型,也允许向下转型

      *  *  *  *  *无论是向上还是向下,两种类型之间必须有继承关系,

      *  *  *  *  *没有继承关系,编译器报错。

==================================================//(举例

复制代码
public class Animal{

        //移动的方法
        
        public void move(){

            System.out.println("动物在移动!!!");
        }

}

//猫类,子类
public class Cat extends Animal{

        //对move方法进行重写
       public void move(){

            System.out.println("猫在走猫步!!!");
        } 
//这个行为是子类型对象特有的方法
public void catchMouse(){
System.out.println("猫正在抓老鼠!!")
}
} //鸟类,子类 public class Bird extends Animal{ //对move方法进行重写 public void move(){ System.out.println(
"鸟儿在飞翔!!!"); } }
复制代码

Animal a1=new Animal();

a1.move();

Cat c1=new Cat();

c1.move();

Bird b1=new Bird();

b1.move();

 

🍓向上转型【子 --->父】 

  Animal a2=new Cat();

  Animal a3=new Bird();

  a2.move();

  a3.move();

  

代码可以这样写吗?可以

/*【解释说明🥥】

  1、Animal和Cat之间有继承关系吗?有的

  2、Animal是父类。Cat是子类

  3、Cat is a Animal,这句话能不能说通?

  4、经过测试得知:父类型的引用允许指向子类型的对象

    Animal a2=new Cat();

    a2就是父类型的引用。

    new Cat()是一个子类型的对象。

    允许a2这个父类型的引用指向子类型的对象

*/

🍓分析:a2.move();

Java程序分为编译阶段运行阶段

📕先来分析编译阶段

对于编译器来说,编译器只知道a2的类型是Animal,所以编译器在检查语法时,会去Animal.class字节码文件中找move()方法,找到了,绑定上move()方法,编译通过,静态绑定成功(编译阶段属于静态绑定。)。

📕再来分析运行阶段

运行阶段的时候,实际上在堆内存中创建的java对象时cat对象,所以move的时候,真正参与move的对象是一只猫,所以运行阶段会动态执行cat对象的move()方法。这个过程属于运行阶段绑定(运行阶段绑定属于动态绑定。)。

⭐多态:

  📧父类型引用指向子类型的对象。

  📧包括编译阶段和运行阶段。

    编译阶段:绑定父类的方法。

    运行阶段:动态绑定子类型对象的方法。

   📧多种形态,多种状态。

❤首要条件❤

无论向上还是向下转型,两种类型之间必须要有继承关系。

没有继承关系,就没有向上还是向下转型。

🐖🐖🐖🐖🐖

Animal a5=new Cat();//底层对象是一只猫

//分析这个程序能否编译和运行?

//分析程序一定要分析编译阶段的静态绑定和运行阶段的动态绑定

//只有编译通过的代码才能运行。没有编译,根本轮不到运行。

a5.catchMouse();//编译错误,在Animal.class文件中找不到catchMouse()方法

 

 

********************************************************************************************

a5.catchMouse();//编译错误,在Animal.class文件中找不到catchMouse()方法

要想编译通过,需要使用向下转型

🍓向下转型【父 --->子】 👇

  什么时候必须使用“向下转型”?

  不要随便做强制类型转换。当你需要访问的是子类对象“特有的”方法,此时必须进行向下转型。

 Cat x=(Cat)a5;

x.catchMouse();//猫正在抓老鼠

//编译通过:因为a5是Animal类型,转成Cat,Animal和Cat之间存在继承关系,所以没报错。

 向下转型有风险吗?

Animal a6=new Bird();//表面上a6是一个Animal,运行的时候实际上是一只鸟儿。

/*

  分析一下程序,编译报错还是运行报错???

    编译器检测到a6这个引用是Animal类型。

    而Animal和Cat之间存在继承关系,所以可以向下转型。

    运行阶段,堆内存实际创建的对象是一个Bird对象。

    在实际运行中,拿着Bird对象转换成Cat对象就不行了。

    因为Bir和Cat之间没有继承关系

运行时出现异常,这个异常和空指针异常一样非常重要,也非常经典:

java.lang.ClassCastException:类型转换异常

java.lang.NullPointerException:空指针异常。这个也非常重要。

*/

Cat y=(Cat)a6;

y.catchMouse();

怎么避免ClassCastException异常的发生???

/*

  ♥运算符:instanceof

第一:instanceof可以在运行阶段动态判断引用指向的对象的类型。

第二:instanceof的语法:

 (引用  instanceof 类型)

第三:instanceof运算符的运算结果只能是:time/false

第四:c是一个引用,c变量保存了内存地址指向了堆中的对象。

 假设(c instanceof Cat)为true表示:

   c引用指向的堆内存中的Java对象是一个Cat。

 假设(c instanceof Cat)为false表示: 

     c引用指向的堆内存中的Java对象不是一个Cat。

程序员要养成一个好习惯:

  任何时候,任何地点,对类型进行向下转型时,一定要使用instanceof 运算符进行判断

if(a6 instanceof Cat){//如果a6是一只Cat
Cat y=(Cat)a6;//再进行强制类型转换
y.catchMouse();
}

 

多态在实际开发中的作用:降低程序的耦合度,提高程序的扩展力

在实际的开发中,客户产生了新的需求。

我们怎么去满足客户的需求?在不使用多态机制的前提下,目前只能在类中添加一个新的方法。

思考:软件在扩展新需求过程中,修改类有什么问题?

  软件在扩展过程中,修改的越少越好。修改的越多,你的系统当前的稳定性就越差,未知的风险就越多。

软件开发原则有七大原则(不属于Java,属于整个软件业)

 

 其中有一条最基本的原则:OCP(开闭原则)

什么是开闭原则?

  对扩展开放,对修改关闭。

  在软件的扩展过程中,修改的越少越好。

高手开发项目不是仅仅为了实现客户的需求,还需要考虑软件的扩展性。

 

 面向父类型编程,面向更加抽象进行编程,不建议面向具体编程。

因为面向具体编程会让软件的扩展力很差

复制代码
package 多态的学习;

public class Testt{
    public  static void main(String[] args){
        Master m=new Master();
        
        Pet pet1=new Cat();
        m.feed(pet1);
        
        Pet pet2=new Dog();
        m.feed(pet2);
  }
    
}

//主人类
 class Master{
void feed(Pet pet){
      pet.eat();
  }
}


//父类

class Pet{
//做一个空实现
void eat(){
    }
}

//子类
class  Cat extends Pet{
void eat(){
System.out.println("猫咪喜欢吃老鼠!!");
  }
}

//子类
class Dog extends Pet{
void eat(){
System.out.println("狗狗喜欢吃骨头!!");
  }
}
复制代码

 

 

 

 ===============================================

总结

💒面向对象的三大特征封装、继承、多态(一环扣一环)

有了封装,有了这种整体的概念之后。

对象和对象之间产生了继承。

有了继承之后,才有了方法的覆盖和多态。

 这里提到了一个软件开发原则:

  七大原则最基本的原则:OCP(对扩展开放,对修改关闭)

  目的是:降低程序耦合度,提高程序扩展力

  面向抽象编程,不建议面向具体编程。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

本文作者:TranquilTimber

本文链接:https://www.cnblogs.com/gbrr/p/16743754.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   喝着农药吐泡泡o  阅读(26)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
💬
评论
📌
收藏
💗
关注
👍
推荐
🚀
回顶
收起
🔑