多态
什么是多态:父类引用指向子类对象
猫 x = new 猫();
动物 y = new 猫();
多态的三个前提是?
1. 要有继承实现关系
2. 要有父类引用指向子类对象.
3. 要有方法的重写
格式:
/*
代码当中体现多态性,其实就是一句话:父类引用指向子类对象。
格式:
父类名称 对象名 = new 子类名称();
或者:
接口名称 对象名 = new 实现类名称();
*/ public static void main(String[] args) { // 使用多态的写法 // 左侧父类的引用,指向了右侧子类的对象 Fu obj = new Zi(); obj.method(); obj.methodFu(); }
多态中调用成员的特点?
a成员变量:
/* 访问成员变量的两种方式: 直接通过对象名称访问成员变量:看等号左边是谁,优先用谁,没有则向上找。 2. 间接通过成员方法访问成员变量:看该方法属于谁,优先用谁,没有则向上找。 public class Demo01MultiField { public static void main(String[] args) { // 使用多态的写法,父类引用指向子类对象 Fu obj = new Zi(); System.out.println(obj.num); // 父:10 // System.out.println(obj.age); // 错误写法! System.out.println("============="); // 子类没有覆盖重写,就是父:10 // 子类如果覆盖重写,就是子:20 obj.showNum(); } } b成员方法:
多态中成员方法的使用特点 /* 在多态的代码当中,成员方法的访问规则是: 看new的是谁,就优先用谁,没有则向上找。 口诀:编译看左边,运行看右边。 对比一下: 成员变量:编译看左边,运行还看左边。 成员方法:编译看左边,运行看右边。 */ public class Demo02MultiMethod { public static void main(String[] args) { Fu obj = new Zi(); // 多态 obj.method(); // 父子都有,优先用子 obj.methodFu(); // 子类没有,父类有,向上找到父类 // 编译看左边,左边是Fu,Fu当中没有methodZi方法,所以编译报错。 // obj.methodZi(); // 错误写法! } }
c静态成员:(稍微看下)
编译看左边, 运行看左边
思路: 静态修饰的成员跟类相关, 跟对象没有关系
Animal a = new Dog();
System.out.prinltn(a.num); // a.num --> 在编译的时候也会翻译成 Animal.num
这时候, 类名是谁, 调用的数据就是谁的.
使用多态的好处
/**无论右边new的是那个子类对象, 左边都不会发生变化,**/
提高代码的扩展性:
可以将一个方法的形参定义为父类类型, 该方法就可以接受这个父类的任意子类对象了
useAnimal(new Dog());
useAnimal(new Cat());
public static void useAnimal(Animal a){
}
使用多态的弊端
弊端: 不能调用子类特有的属性和行为. 问题: 非要调用怎么办? 向下转型. 向下转型的注意事项: 1. 向下转型必须发生在子父类的关系当中 Animal a = new Dog(); Cat c = (Cat)a; // Dog和Cat没有子父类关系. 2. 向下转型必须要事前转上去, 才能转下来 Animal a = new Animal(); Dog d = (Dog)a; // 没有提前转上去. 正确案例: Animal a = new Dog(); Dog d = (Dog)a;
------------------------------------
向上转型
1.多态的使用就是向上转型
1.Animal a = new Dog();// 父类引用指向子类对象
注意事项:向上转型一定是安全的,从小范围转向大范围.
类似于double num=100; 正确 今天->double 自动类型转换
向下转型
弊端:不能访问子类的特有方法.
解决方案:用对象的向下转型.
Animal a = new Dog();/**多态的使用就是想上转型*/
Dog d = (Dog)a; /**父类的a 转型为Dag 的 d*/
注意: 向下转型的强转必须发生在子父类的关系内, 而且必须是转上去, 才能转下来.
什么情况下需要用到向下转型?
答: 为了调用子类特有的属性和行为.
ClassCastException(类型转换异常): 引用数据类型的强转, 出现了错误.
例如:
1. Animal a = new Cat();
Dog d = (Dog)a; --> Cat和Dog之间没有子父类关系, 不能强转
2. Animal a = new Animal();
Dog d = (Dog) a; --> 必须要先进行向上转型, 才可以将数据正常的转型下来.
如果一个方法的参数是一个类名(多态 其实调用传入的是地址值) ???
用instanceof关键字进行类型判断,(稍微看一下,不是重点,就是一个方法,理解)
>* instanceof关键字的作用是什么?
你好,这个关键字的用法是:A instanceof B ,返回值为boolean类型,用来判断A是否是B的实例对象或者B子类的实例对象。如果是则返回true,否则返回false。 如:Person p = new Person() ; // Man m = new Man() ; //Man是Person的子类 Animal a = new Animal() ; m instanceof Man //返回true m instanceof Animal//返回false m instanceof Person//返回true
总结:
1. 判断左边的引用, 是否是右边的数据类型.
/*
如何才能知道一个父类引用的对象,本来是什么子类?
格式:
对象 instanceof 类名称 这将会得到一个boolean值结果,也就是判断前面的对象能不能当做后面类型的实例。 */ public class Demo02Instanceof { public static void main(String[] args) { Animal animal = new Dog(); // 本来是一只狗 animal.eat(); // 狗吃SHIT // 如果希望掉用子类特有方法,需要向下转型 // 判断一下父类引用animal本来是不是Dog if (animal instanceof Dog) { Dog dog = (Dog) animal; dog.watchHouse(); } // 判断一下animal本来是不是Cat if (animal instanceof Cat) { Cat cat = (Cat) animal; cat.catchMouse(); } giveMeAPet(new Dog()); } public static void giveMeAPet(Animal animal) { if (animal instanceof Dog) { Dog dog = (Dog) animal; dog.watchHouse(); } if (animal instanceof Cat) { Cat cat = (Cat) animal; cat.catchMouse(); } } }