动力节点——多态(十三)

​一,多态的概述

1,定义

一类事物的多种形态就叫多态

eg:

水、汽、冰……本质是一种事物,但是按照某个维度去考虑,可以体现不同形态。


多态时面向对象思想的特征,和任何编程语言没有关系,只是java语言为了实现面向对象思想,

则必须在语言中实现的多态。

2,在java语言中如何实现的多态

多态是以继承为基础

多态是以防范重写为基础(如果继承中没有使用方法重写,则使用多态就失去其使用目的)。

多态的语法:

        父类名称    对象名称=new    子类对象名称(参数值);


二,多态的使用目的

1,提高编码效率

2,使用多态可以使得编写的类符合设计模式中的开放封闭原则

开放封闭:是在编写类时的一种指导原则。

对扩展开放,对类的代码为了符合需要修改代码封闭。

对扩展开放:可以扩展功能(在目前的知识中可以使用继承思想)

对修改封闭:类的代码为了满足需求,尽量应该不在修改自身代码。


以上的例子中,饲养员类的代码在使用多态之前,随着动物类的增多要不停修改代码;

在使用多态以后,不管增加多少动物类,都不用修改代码。

3,为了面向接口编程做准备。

//动物类

class  Animal{

        String  color;

        int  age;

        public  void  sleep(){}

        public  void  eatFood(){}

}

//定义猫类继承动物类

class  Cat2  extends  Animal{

        //重写动物类中的吃东西方法

        public  void  eatFood(){

                System.out.println("猫吃鱼");

        }

        public  void  catchMouse(){}

}  

//定义狗类继承动物类

class  Dog2  extends  Animal{

        //重写动物类中的吃东西方法

        public  void  eatFood(){

                System.out.println("狗吃肉");

        }

        public  void  careRoom(){}

}

//定义猪类继承动物类

class  Big2  extends  Animal{

        //重写动物类中的吃东西方法

        public  void  eatFood(){

                System.out.println("猪吃饲料");

        }

}

//定义一个饲养员类

class  SYY{

        /*

        //喂猫

        public  void  FoodCat(Cat2  xx){

                xx . eatFood();//猫吃食物

        }

        //喂狗

        public  void  FoodDog(Dog2  xx){

                xx.eatFood();//狗吃食物

        }

        //喂猪

        public  void  FoodPig(Pig2  xx){

                xx.eatFood();//猪吃食物

        }

        饲养员的代码,每养一种动物,就需要添加哪种动物的喂养方式,也就是说,这个

        饲养员的类要不停的修改代码。

        怎么样做到动物类添加,饲养员不用修改代码?

        这是就可以使用多态去解决问题。

        */


        //无论是喂猫、狗、猪还是其它动物,都叫喂动物

        public  void  foodAnimal(Animal  xx){

                xx.eatFood();

        }

}

public  class  DuoTaiDemo{

        public  static  void  main(String[]  args){

                //创建饲养员对象

                SYY  ss=new  SYY();

                // 创建动物类对象

                //Cat2  cc=new  Cat2();

                //Dog2  dd=new  Dog2();

                //Pig2  pp=new  Pig2();

                //开始喂养动物

                //ss.foodCat(cc);

                //ss.foodDog(dd);

                //ss.foodPig(pp);

                

                //使用多态的创建对象以及使用方式

                Animal  cc=new  Cat2();

                Animal  cc=new  Dog2();

                Animal  cc=new  Pig2();

                //开始喂养动物

                ss.foodAnimal(cc);//猫吃鱼

                ss.foodAnimal(dd);//狗吃肉

                ss.foodAnimal(pp);//猪吃饲料

        }

}


三,多态对成员变量的影响:

1,编译时:

如果成员变量在父类存在,则在使用中才是正确的,编译时看父类

2,执行时:

执行时看父类

class  Fu{

        int  a=10;

        public  void  test(){

                System.out.println("父类test");

        }

}

class  Zi  extends  Fu{

        int  b=20;

        int  a=30;

        public  void  test(){

                System.out.println("子类test");

        }

}

public  class  DuoTaiDemo1{

        public  static  void  main(String[]  args){

                //使用多态

                Fu  xx=new  Zi();

                //开始测试成员变量

                System.out.println(xx.a);//10

                System.out.println(xx.b);//b不是父类的成员变量,所以编译错误,找不到。

        }

}


四,多态对成员方法的影响:

1,如果父类和子类发生方法重写,那么在多态使用中也是执行子类的。

2,编译

编译时,如果调用代码中的方法在父类中存在,则正确;否则就错误。

编译时看父类。

3,执行时执行子类。

class  Fu1{

        public  void  test1(){

                System.out.println("父类test1");

        }

        public  void  test2(){

                System.out.println("父类test2");

        }

}

class  Zi1  extends  Fu1{

        public  void  test1(){

                System.out.println("子类test1");

        }

        public  void  test3(){

                System.out.println("子类test3");

        }

}

public  class  DuoTaiDemo2{

        public  static  void  main(String[]  args){

                //使用多态

                Fu1  xx=new  Zi1();

                //测试调用方法

                xx . test1();//子类的Test1

                //xx.test();//父类没有test3方法,所以编译错误

                xx.test2();

        }  

}


五,静态绑定和动态绑定

静态绑定也叫编译期绑定

就是只看代码,不考虑执行过程,产生的类和类之间的关系。

饲养员中的喂养动物的方法,在编译期,只是饲养员类的方法和动物绑定(只知道动物类型,不清楚是什么动物)。

动态绑定也叫运行期绑定

饲养员中的喂养动物的方法,在运行期,是可以自动辨别传入的动物类的引用具体指向什么类型,这叫动态绑定。

eg:

前面的饲养员喂动物的例子


六,多态中的向上转型和向下转型

1,向上转型

在认知中,往往认为父类在上面,子类在下面(也符合常见的编码方式)

多态的语法中

        父类名称    引用=new    子类名称();

上面的语句是把子类对象赋值给父类引用,就是向上转型。

所以使用多态就是是使用向上转型。

2,向下转型

强制把父类引用转为子类引用,就可以利用这个子类引用来调用子类对象的特有成员了。

语法:

        子类名称    引用=(子类名称)多态中的父类引用;

class  Fu2{

        public  void  test(){

                System.out.println("父类test");

        }

}

class  Zi2  extends  Fu2{

        public  void  test(){

                System.out.println("子类test");

        }

        //子类的特有方法

        public  void  test1(){

                System.out.println("子类test1");

        }

}

public  class  DuoTaiDemo3{

        public  static  void  main(String[]  args){

                Fu2  xx=new  Zi2();

                //xx . test1();错误的

                //但是实际上使用多态时,创建的就是子类对象

                //所以按照对象的调用成员方法的方式,应该能调用子类对象的test1方法使用。

                

                //如果有以上需求,就是在多态中使用子类对象的特有成员

                //就可以使用多态的向下转型(把父类引用强制转为子类引用)

                Zi2  yy=(Zi2)xx;//执行这句代码后,xx还是父类引用,但是多了一个yy引用,指向的是子类。

                yy.test1();//此时就可以使用指向子类对象的yy引用来调用子类对象的特有成员。

        }

}


七,多态内存图解

class  Fu3{

        int  a=10;

        public  void  test(){

                System.out.println("父类test");

        }

}

class  Zi3  extends  Fu3{

        int  b=20;

        int  a=30;

        public  void  test(){

                System.out.println("子类test");

        }

        public  void  test1(){

                System.out.println("子类test1");

        }

}

public  class  DuoTaiDemo4{

        public  static  void  main(String[]  args){

                Fu3  xx=new  Zi3();

                Zi3  yy=(Zi3)xx;

        }

}



八,instanceof讲解

用于多态环境,可以通过它判读某个多态引用类型的真实类型。

语法:

引用名称    instanceof    类的全名称

class  Animal{

        String  color;

        int  age;

        public  void  sleep(){}

}

class  Cat  extends  Animal{

        public  void  sleep(){

                System.out.println("猫类重写动物类的sleep方法");

        }

        public  void  catchMouse(){

                System.out.println("猫抓老鼠");

        }

}

class  Dog  extends  Animal{

        public  void  sleep(){

                System.out.println("狗类重写动物类的sleep方法");

        }

        public  void  careRoom(){

                System.out.println("狗看家");

        }

}

class  T{

        //多态的使用

        public  void  test(Animal  xx){

                //调用猫类的抓老鼠方法

                //xx.catchMouse();因为使用多态,所以不能直接调用catchMouse方法

                //需要向下转型

                //java.long.ClassCastException     原因是在调用时虽然传入的参数是Animal类型,但是

                //实际数据类型是Dog,把Dog强制转为Cat类型,肯定错误。

                //以下代码执行,如果不是则会报出提示

                if(!(xx  instanceof  Cat)){

                        System.out.println("传入的xx的实际类型不是Cat类型");

                        return;

                }

                Cat  yy=(Cat)xx;

                yy.catchMouse();

        }

}

public  class  DuoTaiDemo5{

        public  static  void  main(String[]  args){

                //多态

                Animal  xx=new  Cat();

                T  tt=new  T();

                tt.test(xx);

        }

}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值