Java——多态

目录

一:认识

        1. 概念

        2. 格式

        3. 案例演示

二:访问特点

1. 成员变量的访问

2. 成员方法的访问

3. 对比(总结)

三:向上转型

 四:向下转型

1. 类转换异常 

2. Instanceof       

五:多态的好处

六:总结


一:认识

        1. 概念

        面向对象的三大特征:封装,继承,多态。多态的前提是 extends 继承 implements 实现;

        多态性指一个对象的多种形态。是对于对象而言的,与类无关;

        2. 格式

        继承:父类名称 对象名= new 子类名称( );

        实现:接口名称 对象名 = new 实现类名称( );

       【即 左父右子

        3. 案例演示

        定义一个 Animal类,然后定义一个 Cat类,最后定义一个测试类:

 我们定义一个AnimalClass类,CatClass类,还有一个测试类,通过向上转型来访问父类的 eat方法。
public class AnimalClass {
    String name;//姓名
    int age;//年龄
    public void eat(){//普通方法
        System.out.println("吃饭饭");
    }
}
public class CatClass extends AnimalClass{
    public void sleep(){
        System.out.println("爱睡觉");
    }
}
public class Demo {
    public static void main(String[] args) {
        //左侧父类引用指向右侧子类对象
        AnimalClass a=new CatClass();
        a.eat();
    }
}
C:\Java\jdk-17.0.11\bin\java.exe "-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2022.1.3\lib\idea_rt.jar=2815:C:\Program Files\JetBrains\IntelliJ IDEA 2022.1.3\bin" -Dfile.encoding=UTF-8 -classpath C:\Test\classDemo\out\production\classDemo Multi01.Demo
吃饭饭

进程已结束,退出代码0

二:访问特点

1. 成员变量的访问

 直接访问:直接通过对象名称访问成员变量,等号左边是谁, 就优先用谁,没有往上找;

 间接访问:通过成员方法间接访问成员变量,成员方法属于谁,就优先用谁,没有往上找;

案例演示:

        我们定义一个父类:AnimalClass , 定义一个子类:CatClass , 再定义一个测试类:Demo ;

测试类中对成员变量分别直接/间接访问;

        另外,父类子类中的成员方法重名,子类优先调用自己的成员方法,若没有,再往上找,调用父类的;

package Multi01;
public class AnimalClass {
    int age=66;//年龄
    public void show(){//普通方法
        System.out.println(age);
    }
}
package Multi01;
public class CatClass extends AnimalClass{
    int age=100;
    public void show(){
        System.out.println(age);
    }
}
package Multi01;
public class Demo {
    public static void main(String[] args) {
        //左侧父类引用指向右侧子类对象
        AnimalClass a=new CatClass();
        System.out.println(a.age);//直接访问成员变量
        System.out.println("=========");
        a.show();//间接通过方法访问成员变量
    }
}
C:\Java\jdk-17.0.11\bin\java.exe "-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2022.1.3\lib\idea_rt.jar=2334:C:\Program Files\JetBrains\IntelliJ IDEA 2022.1.3\bin" -Dfile.encoding=UTF-8 -classpath C:\Test\classDemo\out\production\classDemo Multi01.Demo
66
=========
100

进程已结束,退出代码0

2. 成员方法的访问

        看 new 的是谁,就优先用谁里面的方法,没有,往上找;

        即对于成员方法来说: 编译看左边,运行看右边;(没有往上找)

        编译是指源文件转换为字节码文件的过程,运行是指执行字节码文件的过程;

        我们定义一个父类:Man,定义一个子类:Child, 再定义一个测试类DemoMan.

public class Man {
    String name;        //成员变量
    public void show(){ //成员方法
        System.out.println(name);
    }
    public void play(){ //成员方法
        System.out.println("这是父类的方法!");
    }
}
package Multi01;
public class Child extends Man{
    String name="刘备备";
    public void show(){ //成员方法
        System.out.println(name);
    }
    public void sleep(){
        System.out.println("这是子类的方法");
    }
}
package Multi01;
public class DemoMan {
    public static void main(String[] args) {
        Man m=new Child();//多态
        //成员方法的调用:编译看左边,执行看右边,没有往上找
        m.show();//子类中的show方法
        m.play();//往上找到父类的成员方法
    }
}
C:\Java\jdk-17.0.11\bin\java.exe "-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2022.1.3\lib\idea_rt.jar=2780:C:\Program Files\JetBrains\IntelliJ IDEA 2022.1.3\bin" -Dfile.encoding=UTF-8 -classpath C:\Test\classDemo\out\production\classDemo Multi01.DemoMan
刘备备
这是父类的方法!

进程已结束,退出代码0

3. 对比(总结)

        成员变量:编译看左边,执行看左边;

        成员方法:编译看左边,运行看右边:

                                                                                                        (图片为转载,非本人绘制)

三:向上转型

        含义:把右侧的 “new 子类名( )”当作父类来使用;

        格式:父类名  对象名 = new  子类名( ),就是多态的格式。

        向上转型一定是安全的,是从小范围到大范围。类似于数据类型的自动类型转换;

         其实咱们前面提到的多态都是向上转型的,这里就不提供代码进行举例;

 四:向下转型

        含义:将父类对象还原成为本来的子类对象;

        格式:子类名 子类对象 = (子类名)父类对象 

        我们定义一个父类 Man,一个子类 Child ,一个测试类DemoMan,将猫向上转型扩大范围当作动物来访问动物中的show,play方法;为了访问猫本身特有的方法,我们将其向下转型还原为本身来访问pure方法;

public class Man {
    String name;        //成员变量
    public void show(){ //成员方法
        System.out.println(name);
    }
    public void play(){ //成员方法
        System.out.println("这是父类的方法!");
    }
}
package Multi01;
public class Child extends Man{
    String name="刘备备";
    public void show(){ //成员方法
        System.out.println(name);
    }
    public void pure(){
        System.out.println("小孩子天真又可爱");
    }
}
package Multi01;
public class DemoMan {
    public static void main(String[] args) {
        Man m=new Child();  //向上转型,孩子扩大范围为man
        //成员方法的调用:编译看左边,执行看右边,没有往上找
        m.show();//编译左边成功,执行右边子类中的show方法
        m.play();//编译左边成功,执行右边子类中的pay,没有往上找

        Child c=(Child) m;//向下转型,还原为Child本身
        c.pure();//调用本类特有的方法
    }
}

1. 类转换异常 

          但是,如果对象创建的时候不是猫,非要向下转型为猫,那么编译器不会报错,但会显示异常( 类转换异常:java.lang.ClassCastException );  

package Multi01;
public class DemoMan {
    public static void main(String[] args) {
        Man m=new Child();  //向上转型,孩子扩大范围为man
        //成员方法的调用:编译看左边,执行看右边,没有往上找
        m.show();//编译左边成功,执行右边子类中的show方法
        m.play();//编译左边成功,执行右边子类中的pay,没有往上找
        Child c=(Child) m;//向下转型,还原为Child本身
        c.pure();//调用本类特有的方法
        System.out.println("========");

        Dog d=(Dog) m;//编译不会报错,但会出现异常
    }
}
C:\Java\jdk-17.0.11\bin\java.exe "-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2022.1.3\lib\idea_rt.jar=4577:C:\Program Files\JetBrains\IntelliJ IDEA 2022.1.3\bin" -Dfile.encoding=UTF-8 -classpath C:\Test\classDemo\out\production\classDemo Multi01.DemoMan
刘备备
这是父类的方法!
小孩子天真又可爱
========
Exception in thread "main" java.lang.ClassCastException: class Multi01.Child cannot be cast to class Multi01.Dog (Multi01.Child and Multi01.Dog are in unnamed module of loader 'app')
	at Multi01.DemoMan.main(DemoMan.java:12)

进程已结束,退出代码1

2. Instanceof       

        那么,我们怎么确定一个父类引用的对象,原本是哪一个类呢?

        在向下转型的时候,我们可以使用 Instanceof 借助 if...else... 语句先判断父类引用的对象原来是哪个类的,再进行下面的操作;

       

        格式:if ( 父类对象 instangceof 子类名 ) {

                                向下转型;

                                方法体;

                        }

package Multi01;
public class DemoMan {
    public static void main(String[] args) {
        Man m=new Child();  //向上转型,孩子扩大范围为man
        //成员方法的调用:编译看左边,执行看右边,没有往上找
        m.show();//编译左边成功,执行右边子类中的show方法
        m.play();//编译左边成功,执行右边子类中的pay,没有往上找

        if(m instanceof Child){
        Child c=(Child) m;//向下转型,还原为Child本身
        c.pure();//调用本类特有的方法
        System.out.println("========");
        }

        if(m instanceof Dog){
        Dog d=(Dog) m;//编译不会报错,但会出现异常
        }
    }
}

五:多态的好处

        多态的好处就是向上转型时,等号左边都是 “ 父类名 对象名 ” ,对象名的类型都是父

类,不需要根据子类对象来 “ 类名 对象名 = new 类名 ” 创建,使用时更加灵活;

        

                                                                                                         (图片为转载,非本人绘制)

六:总结

        在我看来,向上转型就是把一个子类进行放大成父类使用,向下转型就是把一个类还原

为它本身进行使用。比如,父类为 Animal,子类为 Dog,向上转型就是把 Dog 当作

Amimal 使用 ,向下转型就是把 Dog 还原为 Dog ,以便访问其特有的方法;

  • 18
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值