面向对象——多态
多态
1. extends继承或者implements实现,是多态性的前提。
2. 一个对象拥有多种形态,这就是:对象的多态性。例如:小明是一个对象,这个对象既有学生形态,也有人类形态。
3. 代码当中体现多态性,其实就是一句话:父类引用指向子类对象。
// 格式:继承
父类名称 对象名 = new 子类名称();
// 或者格式:接口
接口名称 对象名 = new 实现类名称();
4. 访问成员变量的两种方式:
-
直接通过对象名称访问成员变量:看等号左边是谁,优先用谁,没有则向上找。
- 间接通过成员方法访问成员变量:看该方法属于谁,优先用谁,没有则向上找。
5. 在多态的代码当中,成员方法的访问规则是:看new的是谁,就优先用谁,没有则向上找。
总结:(编译只的是编译时,即eclipse、IDEA等集成软件中敲代码时;运行时点击运行后)
- 成员方法:编译看左边,运行看右边。
- 成员变量:编译看左边,运行还看左边。
6. 好处:无论右边new的时候换成那个子类对象,等号左边调用方法都不会变化。
7. 对象的向上转型,其实就是多态写法:格式:父类名称 对象名 = new 子类名称();
a. 含义:右侧创建一个子类对象,把它当做父类来看待使用。
b. 注意事项:
向上转型一定是安全的。从小范围转向了大范围。
弊端:对象一旦向上转型为父类,那么就无法调用子类原本持有的内容。
8. 对象的向下转型,其实是一个【还原】的动作。
a. 格式:子类名称 对象名 = (子类对象) 父类对象;
b. 含义:将父类对象,【还原】成本来的子类对象。
c. 注意事项:(以父类:动物类 子类:猫类 狗类为例)
必须保证对象本来创建的时候,就是猫,才能向下转型成为猫。
如果对象创建的时候不是猫是狗,现在非要向下转型成为猫,就会报错<ClassCastException 类转换异常>。
9. 如何才能知道一个父类引用的对象,本来是什么子类?
a. 格式: 对象 instanceof 类名称
b. 这将会得到一个boolean值结果,也就是判断前面的对象能不能当做后面类型的实例。
10. 代码案例
package cn.sunxn.interfacetest.demo06;
public abstract class Animal {
public abstract void eat();
}
package cn.sunxn.interfacetest.demo06;
public class Cat extends Animal {
@Override
public void eat() {
System.out.println("猫吃鱼");
}
// 子类特有方法
public void catchMouse() {
System.out.println("猫抓老鼠");
}
}
package cn.sunxn.interfacetest.demo06;
public class Dog extends Animal {
@Override
public void eat() {
System.out.println("狗吃SHIT");
}
public void watchHouse() {
System.out.println("狗看家");
}
}
package cn.sunxn.interfacetest.demo06;
/**
* 向上转型一定是安全的,没问题的,正确的。但是也有一个弊端:
* 对象一旦向上转型为父类,那么就无法调用子类原本特有的内容
* 解决方案:对象的向下转型【还原】
*/
public class Demo01Main {
public static void main(String[] args) {
// 对象的向上转型,就是:父类引用指向子类对象。
Animal animal = new Cat(); // 本来创建的时候就是一只猫
animal.eat();
// animal.catchMouse(); // 编译错误!对象一旦向上转型为父类,那么就无法调用子类原本持有的内容。
// 向下转型,进行“还原”动作
Cat cat = (Cat) animal;
cat.catchMouse(); //猫抓老鼠
// 下面是错误的向下转型
// 本来new的时候是一直猫,现在非要当成狗
// 错误写法,编译不会报错,但是运行会出现异常
// ClassCastException类转换异常
/*Dog dog = (Dog) animal;
dog.watchHouse();*/
}
}
package cn.sunxn.interfacetest.demo06;
/**
* 如何才能知道一个父类引用的对象,本来是什么子类?
*/
public class Demo02Instanceof {
public static void main(String[] args) {
Animal animal = new Dog();
animal.eat();
// 如果希望调用子类特有方法,需要向下转型
// 判断一下父类引用animal本来是不是Dog
if (animal instanceof Dog) {
Dog dog = (Dog) animal;
dog.watchHouse();
}
// 判断一下animal本来是不是Cat
if (animal instanceof Cat) {
Cat cat = (Cat) animal;
cat.catchMouse();
}
giveMePet(new Dog());
}
public static void giveMePet(Animal animal) {
if (animal instanceof Dog) {
Dog dog = (Dog) animal;
dog.watchHouse();
}
if (animal instanceof Cat) {
Cat cat = (Cat) animal;
cat.catchMouse();
}
}
}