Java中的多态

多态概述

Java作为面向对象的语言,同样可以描述一个事物的多种形态。如Student类继承了Person类,
	    一个Student的对象便既是Student,又是Person。
Java中多态的代码体现在一个子类对象(实现类对象)既可以给这个子类(实现类对象)引用变量赋值,
		又可以给这个子类(实现类对象)的父类(接口)变量赋值。
如Student类可以为Person类的子类。那么一个Student对象既可以赋值给一个Student类型的引用,
		也可以赋值给一个Person类型的引用。
最终多态体现为父类引用变量可以指向子类对象。
多态的前提是必须有子父类关系或者类实现接口关系,否则无法完成多态。
在使用多态后的父类引用变量调用方法时,会调用子类重写后的方法。

多态的前提条件:

       1.必须存在继承关系 (extends)
       2.必须存在方法重写
               子类需要覆盖父类的功能
                   Animal
                           eat():"动物都需要吃饭..."
                   Cat
                           eat() "猫吃鱼"
                   Dog
                           eat() "狗吃骨头"
       3.必须有父类引用指向子类对象
           class Fu{}
           class Zi extends Fu{
               //存在重写
           }
           格式: Fu fu = new Zi()
//动物类
class Animal{
    int age = 10 ;
    public void eat(){
        System.out.println("动物饿了就需要吃饭...");
    }
    public Animal(){
        System.out.println("Animal的无参构造方法");
    }

    //父类的静态show
    public static void show(){
        System.out.println("show animal...");
    }
}
//动物类
class Animal{
    int age = 10 ;
    public void eat(){
        System.out.println("动物饿了就需要吃饭...");
    }
    public Animal(){
        System.out.println("Animal的无参构造方法");
    }

    //父类的静态show
    public static void show(){
        System.out.println("show animal...");
    }
}
/测试类
public class DuoTaiDemo {
    public static void main(String[] args) {
        //使用多态来进行测试
        //父类引用指向子类对象
//        格式: Fu fu = new Zi() ;
        Animal a  = new Cat() ;
        System.out.println(a.age);
        a.eat();
//        a.show() ;//静态方法当然推荐这种访问

       // Animal.show();
        //Cat.show();
    }
}

多态的好处:

  •  1)提高代码的复用性:由继承保证
    
  •  2)提高了代码的扩展性:由多态保证 (重点)   Fu fu = new Zi() ; 父类引用可以指向子类对象
    

多态成员的访问特点:

  •      Fu f = new Zi() ;
            成员变量:编译看左(看Fu类是否存在变量,存在,编译不会报错!)
                     运行看左(使用Fu类的东西)
    
  •          成员方法:(一般没有明确是静态方法的都是----->非静态)
                    编译看左(看Fu类是否存在这个方法,存在,编译不会报错!)
                    运行看右(存在方法重写,所以最终子类的功能将父类的该功能进行覆盖!)
    
  •          静态的方法:
                    编译看左看Fu类是否存在这个静态方法,存在,编译不会报错!),
                    运行看左(静态方法:子类出现了父类一模一样的静态方法,算不上重写,跟类相关的---->类成员)
                                静态功能推荐的方式:类名.访问
    
  •          构造方法:
                    即使多态的情况进行测试,多态的前提条件---->继承关系
                    当前执行子类的构造方法之前,需要让父类的先进行初始化,然后子类进行初始化(分层初始化!)
    
class Fu{

    public Fu() {
        System.out.println("class Fu(){}");
    }

    //父类的成员变量
    int num = 100 ;

    public void show(){
        System.out.println("show Fu...");
    }

    public static void method(){
        System.out.println("method Fu...");
    }
}
class Zi extends  Fu{

    public Zi() {
        System.out.println("class Zi(){}");
    }

    //子类的成员变量
    int num = 200 ;

    @Override
    public void show() {
        System.out.println("show Zi...");
    }

    public  static void method(){
        System.out.println("method Zi...");
    }
}
//测试类
public class DuoTaiDemo {
    public static void main(String[] args) {
        //使用多态的格式:Fu f = new Zi() ;
        Fu f = new Zi() ;
//        Zi z = new Zi( );  //之前的写法  z.num:就近原则
        System.out.println(f.num);
        System.out.println("-------------------------");
        f.show() ;
        System.out.println("--------------------------");
        f.method() ;
        Fu.method();
        Zi.method();
    }
}

运行结果:

100
-------------------------
show Zi...
--------------------------
method Fu...
method Fu...
method Zi...

多态的弊端:

  •      不能访问子类的特有功能   (Fu f = new Zi())
                    f.方法名() ;报错了. 父类中没有子类特有功能!
    
  •      如何解决多态的弊端?
            方案1: (不推荐)
                    具体的子类创建具体的子类对象  Zi z = new Zi() ;
                    z.成员方法名() ;
                   本身Fu f = new Zi() ;已经在堆内存中开辟空间了
                   Zi z = new Zi() ;在堆内存中又开辟空间,从内存角度考虑,这种比较消耗内存空间,不太好!
             方案2:(推荐使用:"向下转型")
                    多态的第三个前提条件:父类 引用指向子类对象      :"向上转型 "Fu f = new Zi() ;
                    能不能将父类的引用转换成子类的引用?   好处:不需要在堆内存开辟空间
                    可以------>"向下转型"
                          Zi z =   (Zi)f ;  还原成子类型
                          强转类型转换: 目标类型 变量名 =(目标类型)初始化值;
                                        基本类型 :   int num =  65 ;
                                          //num--->char类型
                                          char ch  = (char)num ; ====>'A'
    
父类
//父类
class Father2{
    public void show(){
        System.out.println("show father...");
    }
}
子类
//子类
class Son2 extends  Father2{
    public void show(){
        System.out.println("show son...");
    }

    //特有功能:
    public void playGame(String gameName){
        System.out.println("会玩"+gameName+"游戏");
    }
}
测试类
//测试类
public class DuoTaiDemo4 {
    public static void main(String[] args) {
        //父类指向子类对象
        Father2 father2 = new Son2() ;
        father2.show(); //编译看左,运行看右,存在重写

        //father2.playGame( "lol");//父类没有方法
        System.out.println("------------------------------");

        //方案1:创建具体的子类对象
        Son2 son2 = new Son2() ;
        son2.playGame("lol");

        System.out.println("------------------------------");
        /**
         * "向下转型"
         *                            Zi z =   (Zi)f ;  还原成子类型
         */

        Son2 s = (Son2) father2;
        s.playGame("csgo");
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值