【JAVA基础】08 面向对象3
1. 多态
-
多态polymorhic概述
- 事物存在的多种形态。
- 多态前提
- 要有继承关系
- 要有方法重写
- 要有父类引用指向子类对象
- 案例演示
- 代码体现多态
-
class Demo1_Polymorphic{ public static void main(String[] args) { Cat c = new Cat(); c.eat(); Animal a = new Cat(); // 父类引用指向子类对象 a.eat(); // 输出“猫吃鱼” } } class Animal { public void eat() { System.out.println("动物吃饭"); } } class Cat extends Animal { public void eat() { System.out.println("猫吃鱼"); } }
- 多态中的成员访问特点
- 成员变量
- 编译看左边(父类),运行看左边(父类)
- Father f = new Son();
-
class Demo2_Polymorphic { public static void main(String[] args) { Father f = new Son(); System.out.println(f.num); //输出10 } } class Father { int num = 10; } class Son extends Father { int num = 20; }
如果再上面例子的基础上,再生成一个Son类对象,则
-
class Demo2_Polymorphic { public static void main(String[] args) { Father f = new Son(); System.out.println(f.num); //输出10 Son s = new Son(); System.out.println(s.num); //输出20 } } class Father { int num = 10; } class Son extends Father { int num = 20; }
- 成员方法
- 编译看左边(父类),运行看右边(子类)——又称“动态绑定”
- Father f = new Son();
- 编译时,看父类中有没有该成员方法,有则编译成功;运行则动态绑定到子类的成员方法上,运行子类的成员方法。
-
class Demo3_Polymorphic { public static void main(String[] args) { Father f = new Son(); f.print();// 输出son } } class Father { int num = 10; public void print() { System.out.println("father"); } } class Son extends Father { int num = 20; public void print() { System.out.println("son"); } }
- 静态方法
- 编译看左边(父类),运行看左边(父类)
- 静态和类相关,算不上重写,所以,访问还是左边的
-
class Demo4_Polymorphic { public static void main(String[] args) { Father f = new Son(); f.method(); //输出"father static method"; // 相当于是Father.method(); 调用父类的方法 } } class Father { int num = 10; public void print() { System.out.println("father"); } public static void method(){ System.out.println("father static method"); } } class Son extends Father { int num = 20; public void print() { System.out.println("son"); } public static void method(){ System.out.println("son static method"); } }
- 总结:
- 只有非静态的成员方法,编译看左边(父类),运行看右边(子类)
- 其他都是编译看左边(父类),运行看左边(父类)
- 成员变量
- 案例:超人的故事
- 通过该案例帮助理解多态的现象。
-
class Demo5_Polymorphic { public static void main(String[] args) { Person p = new SuperMan(); // 父类引用指向子类对象,超人提升为人 System.out.println(p.name);// 输出“John” p.谈生意(); // 输出"谈几个亿的大单子" //p.fly(); //编译出错 } } class Person { String name = "John"; public void 谈生意() { System.out.println("谈生意"); } } class SuperMan extends Person { String name = "Super man"; public void 谈生意() { System.out.println("谈几个亿的大单子"); } public void fly() { System.out.println("飞出去救人"); } }
超人作为人类身份的属性信息对外展示,Person类和SuperMan类中重写的方法,实际执行的是超人身份的方法;
在这个例子中,父类中没有fly方法,故编译失败,也无法执行。针对这个,要考虑下面的 向上转型和向下转型 的问题。
- 多态中 向上转型和向下转型
- 向上转型
- Person p = new SuperMan();
- 父类引用指向子类对象,就是向上转型
- 向下转型
- SuperMan sm = (SuperMan)p;
-
class Demo5_Polymorphic { public static void main(String[] args) { Person p = new SuperMan(); // 父类引用指向子类对象,超人提升为人 System.out.println(p.name);// 输出“John” p.谈生意(); // 输出"谈几个亿的大单子" //p.fly(); //编译出错 SuperMan sm = (SuperMan)p; // 向下转型 sm.fly(); } } class Person { String name = "John"; public void 谈生意() { System.out.println("谈生意"); } } class SuperMan extends Person { String name = "Super man"; public void 谈生意() { System.out.println("谈几个亿的大单子"); } public void fly() { System.out.println("飞出去救人"); } }
- 向上转型
-
补充参考:基本数据类型:
- 自动类型提升
- 强制类型转换
-
class Demo1_Polymorphic{ public static void main(String[] args) { int i = 10; byte b = 20; i = b; // 自动类型转换 b = (byte)i; // 强制类型转换 } }
- 多态的好处和弊端
- 多态的好处
- 提高了代码的维护性(继承保证)
- 提高了代码的扩展性(由多态保证)
- 可以当做形式参数
- 可以接收任意子类对象
- 多态的弊端
- 不能使用子类的特有属性和行为
- 案例演示
- method(Animal a) 方便Animal的所有子类的 重写的方法调用
- method(Cat c) 这种直接调用子类,出现并行子类,调用父类方法,需要些新的method方法,传入不同的类作为实参。
-
class Demo6_Polymorphic { public static void main(String[] args) { method(new Cat()); method(new Dog()); /* Animal a = new Cat(); Animal a = new Dog(); 开发的时候很少在创建对象的时候用父类引用指向子类对象, 直接创建子类对象更方便,可以使用子类中的特有属性和方法 */ } /* public static void method(Cat c) { c.eat(); } public static void method(Dog d) { d.eat(); }*/ public static void method(Animal a) { // 当做参数的时候,用多态最好,扩展性强 //关键字 instanceof 判断前边的引用是否是后边的数据类型 if (a instanceof Cat) { Cat c = (Cat)a; c.eat(); c.catchMouse(); }else if (a instanceof Dog) { Dog d = (Dog)a; d.eat(); d.lookHome(); }else { a.eat(); } /* // 如果把Dog强转成Cat,就会出现类型转换异常,ClassCastException Cat c = (Cat)a; c.eat(); c.catchMouse();*/ } } class Animal { public void eat() { System.out.println("动物吃饭"); } } class Cat extends Animal { public void eat() { System.out.println("猫吃鱼"); } public void catchMouse() { System.out.println("抓老鼠"); } } class Dog extends Animal { public void eat() { System.out.println("狗吃肉"); } public void lookHome() { System.out.println("看家"); } }
- 多态的好处