13_Java中的多态
Java中的多态
一、多态的概述
1、同一个对象,在不同时刻表现出来的不同形态
2、多态的前提和体现
有继承/实现关系
有方法重写
有父类引用指向子类对象
3、代码示例:
package com.itheima_01; /* 动物类 */ public class Animal { public void eat(){ System.out.println("动物吃东西"); } }
package com.itheima_01; /* 猫类 */ public class Cat extends Animal{ //此处完成继承关系 @Override public void eat(){ //此处实现方法重写 System.out.println("猫吃老鼠"); } }
package com.itheima_01; /* 测试类, 用于测试多态前提 */ public class AnimalDemo { public static void main(String[] args){ //父类引用指向子类对象 Animal animal = new Cat(); //可以看到此时 调用eat方法实现的是猫吃老鼠 animal.eat(); } }
二、多态中成员访问特点
成员变量:编译看左边,执行看左边
成员函数:编译看左边,执行看右边
为什么成员变量与成员方法的访问不一样呢?
因为成员方法有重写,而成员变量没有
参考代码:
package com.itheima_02; /* 动物类 */ public class Animal { public int age = 40; public void eat(){ System.out.println("动物吃东西"); } }
package com.itheima_02; /* 猫类 */ public class Cat extends Animal{ public int age = 20; public int weight = 10; @Override public void eat(){ System.out.println("猫吃老鼠"); } public void playGame(){ System.out.println("猫捉迷藏"); } }
package com.itheima_02; /* 测试类 */ public class AnimalDemo { public static void main(String[] args){ //有父类引用指向子类对象 Animal a = new Cat(); //在多态中 针对于属性而言 编译与运行都是以 左边(此处是父类引用)为准 System.out.println(a.age); // System.out.println(a.weigth); //在多态中 针对于方法而言 编译以左边为准 运行则是看右边 a.eat(); // a.playGame(); } }
三、多态的好处和弊端
1、多态的好处:
提高了程序的拓展性,具体体现:定义方法的时候,使用父类作为参数,将来使用的时候,传入具体的子类类型参与操作
2、多态的弊端:
不能使用子类的特有功能(理解:多态是通过父类引用进行方法的调用,但是子类中的特有方法无法通过父类引用进行调用)
3、参考代码:
package com.itheima_03; /* 动物操作类 */ public class AnimalOperator { /*public void useAnimal(Cat c){ //Cat c = new Cat(); c.eat(); } public void useAnimal(Dog d){ //Dog d = new Dog(); d.eat(); }*/ //利用多态思想 传入我所需要的对应的子类对象 public void useAnimal(Animal a){ a.eat(); // a.lookDoor(); 不能利用父类引用访问子类特有的功能 } }
package com.itheima_03; public class Cat extends Animal{ @Override public void eat(){ System.out.println("猫吃老鼠"); } }
package com.itheima_03; public class Dog extends Animal{ @Override public void eat(){ System.out.println("狗吃骨头"); } public void lookDoor(){ System.out.println("狗看门"); } }
package com.itheima_03; public class Pig extends Animal{ @Override public void eat(){ System.out.println("猪吃饲料"); } }
package com.itheima_03; /* 动物操作类 */ public class AnimalOperator { /*public void useAnimal(Cat c){ //Cat c = new Cat(); c.eat(); } public void useAnimal(Dog d){ //Dog d = new Dog(); d.eat(); }*/ //利用多态思想 传入我所需要的对应的子类对象 public void useAnimal(Animal a){ a.eat(); // a.lookDoor(); 不能利用父类引用访问子类特有的功能 } }
package com.itheima_03; public class AnimalDemo { public static void main(String[] args) { //创建动物操作类的对象,调用方法 AnimalOperator ao = new AnimalOperator(); /*Cat c = new Cat(); ao.useAnimal(c); Dog d = new Dog(); ao.useAnimal(d);*/ //可以看到:每添加一个类,就要到动物操作类中去添加新的方法(也可以使用上面注释的方法传参) Animal a = new Cat(); ao.useAnimal(a); a = new Dog(); ao.useAnimal(a); a = new Pig(); ao.useAnimal(a); } }
四、多态中的转型
1、向上转型:
从子到父,父类引用指向子类对象(就是多态条件操作)
2、向下转型:
从父到子,父类引用转换为子类对象
例如:Animal a = new Cat(); Cat c = (Cat)a; 注意a,c中存放的引用类型相同才可进行 这里都是Cat类在堆区的地址值
3、代码示例:
package com.itheima_04; public class Animal { public void eat(){ System.out.println("动物吃东西"); } }
package com.itheima_04; public class Cat extends Animal{ @Override public void eat(){ System.out.println("猫吃老鼠"); } public void playGame(){ System.out.println("猫捉迷藏"); } }
package com.itheima_04; /* 向上转型 从子到父 父类引用指向子类对象 向下转型 从父到子 父类引用转为子类对象 */ public class AnimalDemo { public static void main(String[] args) { //多态 Animal a = new Cat(); //向上转型 a.eat(); // a.playGame(); //报错编译看左边 /* //创建Cat对象 Cat c = new Cat(); c.eat(); c.playGame();*/ //向下转型 Cat c = (Cat)a; //强制转换 a中存的也是Cat的堆区地址值才行,如果此时不是就会报错 c.playGame(); } }
五、多态案例
1、案例一猫和狗:
package com.itheima_05; /* 动物类 */ public class Animal { //成员属性 private String name; private int age; //构造方法 public Animal(){ } public Animal(String name, int age){ this.name = name; this.age = age; } //set/get/show方法 public void setName(String name){ this.name = name; } public String getName(){ return this.name; } public void setAge(int age){ this.age = age; } public int getAge(){ return this.age; } public void show(){ System.out.println(getName() + "," + getAge()); } //定义一个吃东西的方法 public void eat(){ System.out.println("动物在吃东西"); } }
package com.itheima_05; /* 猫类 */ public class Cat extends Animal{ //构造方法 public Cat() { } public Cat(String name, int age) { super(name, age); } @Override public void eat(){ System.out.println("猫吃老鼠"); } }
package com.itheima_05; /* 狗类 */ public class Dog extends Animal{ //构造方法 public Dog() { } public Dog(String name, int age) { super(name, age); } @Override public void eat(){ System.out.println("狗吃骨头"); } }
package com.itheima_05; /* 测试类 */ public class AnimalDemo { public static void main(String[] args){ //实现猫类的调用 Animal a = new Cat(); /* 此处如果我们创建子类对象也只会到父类中去找属性和方法,我们并没有在子类中写 所以直接利用父类引用来调用方法、来实现初始化 当我们是使用子类引用来调用时,就需要参考继承中的调用规则中 */ //Cat c = (Cat)a; 一般又用于调用子类中特有的方法此处没有 a.setName("加菲猫"); a.setAge(8); a.show(); a.eat(); Animal a2 = new Cat("Tom", 6); a2.show(); a2.eat(); //实现狗类的调用 Animal a3 = new Dog(); a3.setName("旺财"); a3.setAge(7); a3.show(); a3.eat(); Animal a4 = new Dog("来福", 5); a4.show(); a4.eat(); } }
本文作者:如此而已~~~
本文链接:https://www.cnblogs.com/fragmentary/p/16751553.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步