多态
代码当中体现多态性,其实就是父类引用指向了类对象
1.1 多态的格式
父类名称 对象名 = new 子类名称();
或者
接口名称 对象名 = new 实现类名称();
1.2 多态中成员变量的使用特点
访问成员变量的两种方式
1.直接通过对象名称访问成员变量:看等号左边是谁,优先用谁,没有则向上找
2.间接通过成员方法访问成员变量:看该方法属于谁,优先用谁,没有则向上找,方法如果在子类没有覆盖重写,就是父;如果覆盖重写,则是子。
fu(){
int num = 10;
showNum(){Sout(num);}
}
zi(){
int num = 20;
int age = 16;
@Override
showNum(){Sout(num);}
}
Demo(){
psvm(String[] args){
fu obj = new zi();
Sout(obj.num);//父,10
// Sout(obj.age);错误写法
//方法如果在子类没有覆盖重写,就是父,10;如果覆盖重写,则是子,20。
obj.showNum();
}
}
1.3 多态中成员方法的使用特点
在多态的代码中,成员方法的访问规则是:
看new的是谁,就优先用谁,没有则向上找。
口诀:编译看左边,运行看右边
fu{
method(){sout("父类方法");}
methodfu(){sout("父类特殊方法");}
}
zi{
method(){sout("子类方法");}
methodzi(){sout("子类特殊方法");}
}
Demo{
psvm(String[] args){
fu obj = new zi();
obj.method();//父子都有method(),优先用子,运行看右,右边是子类,则用子类。
obj.methodfu();//子类没有,父类有,则向上找到父类
// obj.methodzi();//编译不用过,编译看左,左边是父类,父类没有methodzi()方法,报错
}
}
1.4 访问成员方法和变量的特点对比
成员变量:编译,运行都看左边
成员方法:编译看左边,运行看右边
1.5 多态的好处
转型:
abstract Animal(){
public abstract void eat();
}
Cat extends Animal(){
@Override
public void eat(){Sout("猫吃鱼");}
catchMouse(){Sout("猫抓老鼠");}
}
Dog extends Animal(){
@Override
public void eat(){Sout("狗吃屎");}
}
Demo01(){
/*
多态的向下转型
向上转型一定是安全的,没有问题,是正确的,但是也有一个弊端
对象一旦向上转型为父类,那就无法调用子类原本特有的内容
解决方案:用对象的向下转型【还原】。
【还原】注意事项:原本创建的是猫类对象,则会还原成猫类对象
*/
psvm(String[] args){
//对象向上转型,父类引用指向子类对象
Animal obj = new Cat();
obj.eat();//编译看左,左边animal有eat方法,则运行看右,右边子类有cat有重写,则运行子类方法。
// obj.catchMouse();//编译报错
Cat cat = (Cat)obj;
cat.catchMouse();//运行成功
Dog dog = (Dog)obj;//报错
}
}
Demo02(){
/*
如何才能知道一个父类引用对象本来是什么子类
格式:
对象 instanceof 类名称
这将会得到一个boolean值结果,也就是判断前面的对象能不能当做后面类型的实例
*/
psvm(String[] args){
Animal obj = new Cat();//本来是一只猫
animal.eat()//猫吃鱼
//如果希望调用子类特有方法,需要向下转型,则需要判断父类引用animal本来是不是Dog
if(animal instanceof Dog){//只有本来是狗,才能本来是狗,才能运行if模块的内容
Dog dog = (Dog)animal;
dog.eat;
}
}
}