09-02 java 多态
多态的前提、多态的特点
/* 多态:同一个对象(事物),在不同时刻体现出来的不同状态。 举例: 猫是猫,猫是动物。 水(液体,固体,气态)。 多态的前提: A:要有继承关系。 B:要有方法重写。 其实没有也是可以的,但是如果没有这个就没有意义。 动物 d = new 猫(); d.show(); 动物 d = new 狗(); d.show(); C:要有父类引用指向子类对象。 父 f = new 子(); 用代码体现一下多态。 多态中的成员访问特点: A:成员变量 编译看左边,运行看左边。 B:构造方法 创建子类对象的时候,访问父类的构造方法,对父类的数据进行初始化。 C:成员方法 编译看左边,运行看右边。 D:静态方法 编译看左边,运行看左边。 (静态和类相关,算不上重写,所以,访问还是左边的) 由于成员方法存在方法重写,所以它运行看右边。 */ class Fu { public int num = 100; public void show() { System.out.println("show Fu"); } public static void function() { System.out.println("function Fu"); } } class Zi extends Fu { public int num = 1000; public int num2 = 200; public void show() { System.out.println("show Zi"); } public void method() { System.out.println("method zi"); } public static void function() { System.out.println("function Zi"); } } class DuoTaiDemo { public static void main(String[] args) { //要有父类引用指向子类对象。 //父 f = new 子(); Fu f = new Zi(); System.out.println(f.num); //找不到符号 // System.out.println(f.num2); f.show(); //找不到符号 // f.method(); f.function(); } }
多态的好处:
/* 多态的好处: A:提高了代码的维护性(继承保证) B:提高了代码的扩展性(由多态保证) 猫狗案例代码 */
//父类,动物类
class Animal { public void eat(){ System.out.println("eat"); } public void sleep(){ System.out.println("sleep"); } } class Dog extends Animal { public void eat(){ System.out.println("狗吃肉"); } public void sleep(){ System.out.println("狗站着睡觉"); } } class Cat extends Animal { public void eat() { System.out.println("猫吃鱼"); } public void sleep() { System.out.println("猫趴着睡觉"); } } class Pig extends Animal { public void eat() { System.out.println("猪吃白菜"); } public void sleep() { System.out.println("猪侧着睡"); } } //针对动物操作的工具类 class AnimalTool { private AnimalTool(){} //不管是什么对象,都是Animal类,这就叫多态拓展性 public static void useAnimal(Animal a) { a.eat(); a.sleep(); } } class test { public static void main(String[] args) { //我喜欢猫,就养了一只 Cat c = new Cat(); //我很喜欢猫,所以,又养了一只 Cat c2 = new Cat(); //我特别喜欢猫,又养了一只 Cat c3 = new Cat(); AnimalTool.useAnimal(c); AnimalTool.useAnimal(c2); AnimalTool.useAnimal(c3); System.out.println("--------------"); //我喜欢狗 Dog d = new Dog(); Dog d2 = new Dog(); Dog d3 = new Dog(); AnimalTool.useAnimal(d); AnimalTool.useAnimal(d2); AnimalTool.useAnimal(d3); System.out.println("--------------"); //我喜欢宠物猪 //定义一个猪类,它要继承自动物,提供两个方法,并且还得在工具类中添加该类方法调用 Pig p = new Pig(); Pig p2 = new Pig(); Pig p3 = new Pig(); AnimalTool.useAnimal(p); AnimalTool.useAnimal(p2); AnimalTool.useAnimal(p3); System.out.println("--------------"); } }
多态的弊端
/* 多态的弊端: 不能使用子类的特有功能。 */ class Fu { public void show() { System.out.println("show fu"); } } class Zi extends Fu { public void show() { System.out.println("show zi"); } public void method() { System.out.println("method zi"); } } class DuoTaiDemo3 { public static void main(String[] args) { //测试 Fu f = new Zi(); f.show(); f.method();//编译看左边,但是左边的Fu没有method方法,会报错。不能使用子类的method方法 } }
多态弊端的解决;
/* 多态的弊端: 不能使用子类的特有功能。 我就想使用子类的特有功能?行不行? 行。 怎么用呢? A:创建子类对象调用方法即可。(可以,但是很多时候不合理。而且,太占内存了) B:把父类的引用强制转换为子类的引用。(向下转型) 对象间的转型问题: 向上转型: Fu f = new Zi(); 向下转型: Zi z = (Zi)f; //要求该f必须是能够转换为Zi的。 */ class Fu { public void show() { System.out.println("show fu"); } } class Zi extends Fu { public void show() { System.out.println("show zi"); } public void method() { System.out.println("method zi"); } } class DuoTaiDemo4 { public static void main(String[] args) { //测试 Fu f = new Zi(); f.show(); //f.method(); //创建子类对象 //Zi z = new Zi(); //z.show(); //z.method(); //你能够把子的对象赋值给父亲,那么我能不能把父的引用赋值给子的引用呢? //如果可以,但是如下 Zi z = (Zi)f; z.show(); z.method(); } }
多态问题的理解:
多态的问题理解: class 孔子爹 { public int age = 40; public void teach() { System.out.println("讲解JavaSE"); } } class 孔子 extends 孔子爹 { public int age = 20; public void teach() { System.out.println("讲解论语"); } public void playGame() { System.out.println("英雄联盟"); } } //Java特别火,很多人来请孔子爹去讲课,这一天孔子爹被请走了 //但是还有人来请,就剩孔子在家,价格还挺高。孔子一想,我是不是可以考虑去呢? //然后就穿上爹的衣服,带上爹的眼睛,粘上爹的胡子。就开始装爹 //向上转型 孔子爹 k爹 = new 孔子(); //到人家那里去了 System.out.println(k爹.age); //40 k爹.teach(); //讲解论语 //k爹.playGame(); //这是儿子才能做的 //讲完了,下班回家了 //脱下爹的装备,换上自己的装备 //向下转型 孔子 k = (孔子) k爹; System.out.println(k.age); //20 k.teach(); //讲解论语 k.playGame(); //英雄联盟
多态继承中的内存讲解:
多态中的对象变化内存图解:
多态中类转换异常:
/* ClassCastException:类型转换异常 一般在多态的向下转型中容易出现 */ class Animal { public void eat(){} } class Dog extends Animal { public void eat() {} public void lookDoor() { } } class Cat extends Animal { public void eat() { } public void playGame() { } } class DuoTaiDemo5 { public static void main(String[] args) { //内存中的是狗 Animal a = new Dog(); Dog d = (Dog)a; //内存中是猫 a = new Cat(); Cat c = (Cat)a; //内存中是猫 Dog dd = (Dog)a; //ClassCastException } }
猫狗案例
/* 多态练习:猫狗案例 */ class Animal { public void eat(){ System.out.println("吃饭"); } } class Dog extends Animal { public void eat() { System.out.println("狗吃肉"); } public void lookDoor() { System.out.println("狗看门"); } } class Cat extends Animal { public void eat() { System.out.println("猫吃鱼"); } public void playGame() { System.out.println("猫捉迷藏"); } } class DuoTaiTest { public static void main(String[] args) { //定义为狗 Animal a = new Dog(); a.eat(); System.out.println("--------------"); //还原成狗 Dog d = (Dog)a; d.eat(); d.lookDoor(); System.out.println("--------------"); //变成猫 a = new Cat(); a.eat(); System.out.println("--------------"); //还原成猫 Cat c = (Cat)a; c.eat(); c.playGame(); System.out.println("--------------"); //演示错误的内容 //Dog dd = new Animal(); //Dog ddd = new Cat(); //ClassCastException //Dog dd = (Dog)a;//这个编译不报错,运行才报错 } }
不同地方饮食文化不同的案例
/* 不同地方饮食文化不同的案例 */ class Person { public void eat() { System.out.println("吃饭"); } } class SouthPerson extends Person { public void eat() { System.out.println("炒菜,吃米饭"); } public void jingShang() { System.out.println("经商"); } } class NorthPerson extends Person { public void eat() { System.out.println("炖菜,吃馒头"); } public void yanJiu() { System.out.println("研究"); } } class DuoTaiTest2 { public static void main(String[] args) { //测试 //南方人 Person p = new SouthPerson(); p.eat(); System.out.println("-------------"); SouthPerson sp = (SouthPerson)p; sp.eat(); sp.jingShang(); System.out.println("-------------"); //北方人 p = new NorthPerson(); p.eat(); System.out.println("-------------"); NorthPerson np = (NorthPerson)p; np.eat(); np.yanJiu(); } }
看程序,出结果:
/* 看程序写结果:先判断有没有问题,如果没有,写出结果 多态的成员访问特点: 方法:编译看左边,运行看右边。 继承的时候: 子类中有和父类中一样的方法,叫重写。 子类中没有父亲中出现过的方法,方法就被继承过来了。 */ class A { public void show() { show2(); } public void show2() { System.out.println("我"); } } class B extends A { /* public void show() { show2(); } */ public void show2() { System.out.println("爱"); } } class C extends B { public void show() { super.show(); } public void show2() { System.out.println("你"); } } public class DuoTaiTest4 { public static void main(String[] args) { A a = new B(); a.show(); B b = new C(); b.show(); } }