为什么要用转型
很多时候,我们需要把很多种类的实例对象,全部扔到一个集合。(这句话很重要)
在这个例子里就是把Thinkpad笔记本,Mouse鼠标,KeyBoard键盘等实例对象,全部扔到一个Shopcar购物车集合。
但是肯定不可能给他们每个种类都用一个独立的集合去存放吧,这个时候我们应该寻找到一个标准,接口就是一个标准。这些都是各种电子产品,抽象成电子产品。然后一个Electronics接口就出来了。
在回到刚才,我们把很多种类的实例对象全部扔到一个集合。或许这样比较好理解:把很多种类的子类实例对象全部扔到存放父类实例的集合。
经过了这个过程,子类实例已经赋值给了父类引用(即完成了向上转型),但很遗憾的丢失了子类扩展的方法。
很好的是Java语言有个向下转型的特性,让我们可以重新获得丢失的方法,即强转回子类
所以我们需要用到子类实例的时候,就从那个父类集合里拿出来向下转型就可以了,一样可以使用子类实例对象
编译时多态:方法重载,在编译时就能进行不同行为的区分
运行时多态:程序运行时动态决定调用哪个方法,引用变量指向哪一种具体类型,变量引发的方法调用的是哪一种类中定义的方法(多态讨论运行时多态)
**多态:**允许不同类的对象对同一消息做出不同的响应(同一个行为,不同对象的表现形式不同)
**多态条件:**1、满足继承关系
2、父类引用指向子类对象
向上转型:子类对象转型为父类对象,称为向上转型,父类引用指向子类实例
animal类型的引用,吃的行为,但随着在运行时实例化的对象类型不同,执行的具体行为能力不同,即多态的表现
Animal one=new Animal("h",5);
Animal two=new Cat("f",6,8);
Animal three=new Dog("d",2,"c");
one.eat();
two.eat();
three.eat();
//animal类型的引用类型相同,吃的行为相同,但随着在运行时实例化的对象类型不同,执行的具体行为能力不同,即多态的表现
可调用子类重写的方法以及父类派生可允许子类直接访问的方法,而无法调用子类特有的方法
向上转型后同名变量的调用
public class Animal {
final int i=33;
public static final int j=45;
static int k=20;
}
public class Cat extends Animal{
final int i=50;
public static final int j=90;
static int k=7;
}
Animal two=new Cat();
System.out.println(new Animal().i);
System.out.println(new Cat().i);//子类重写变量后,子类变量占优势
System.out.println(new Animal().j);
System.out.println(new Cat().j);
System.out.println(Animal.j);//类引用,该类占优势
System.out.println(Cat.j);
System.out.println(two.i);//向上转型后调用final和static final、static变量,仍然指向父类的内部信息
System.out.println(two.j);
System.out.println(two.k);
向下转型:强制类型转换,子类引用指向父类实例,满足转换条件才能转换
Cat temp=(Cat)two;
temp.eat();
instanceofi:判断左边对象是否满足右边类的实例特征,提高向下转型的安全性
以下均满足转型条件
if(two instanceof Cat){//指向cat
System.out.println("转型");
}
if(two instanceof Animal){//animal是cat的父类?
System.out.println("转型");
}
if(two instanceof Object){//object是animal的父类?
System.out.println("转型");
}
父类中的静态方法,在子类中不能被重写,只能被继承(类似final),若没有override注解,该方法算子类独有的方法,与父类的方法不构成重写关系,父类中的静态方法无法被子类重写,所以向上转型之后,只能调用父类中原有的静态方法
public static void eat(){
System.out.println("吃东西");
}
@Override//有这个注解必须满足重写条件
public static void say(){
System.out.println("SAY2");//类共享,只允许被子类继承,无法被重写
}
没有override注解,该方法算子类独有的方法,与父类的方法不构成重写关系
public static void say(){
System.out.println("SAY2");
two.say();//父类中的静态方法无法被子类重写,所以向上转型之后,只能调用父类中原有的静态方法
多态应用:向下转型
```java
/*
喂猫,玩球
喂狗,睡觉
*/
//方案一:编写方法,传入不同类型的动物,调用各自的方法
public void feedDog(Dog dog){
dog.sleep();
}
public void feedCat(Cat cat){
cat.eat();
}
/*
方案二:编写方法传入动物的父类,方法中通过类型转换,调用指定子类的方法,使用灵活
*/
public void feed(Animal animal){
if(animal instanceof Cat){
Cat a=(Cat)animal;
a.eat();}
else if(animal instanceof Dog)
{Dog a=(Dog)animal;
a.sleep();}
}
Master master=new Master();
Cat cat=new Cat();
master.feedCat(cat);
master.feedDog(dog);
Animal a1=cat;
master.feed(a1);
多态应用二:向上转型
/*
饲养宠物
空闲时间多,养狗
空闲时间少,养猫
同一个操作行为针对不同的参数,返回不同的实例对象,完成不同的操作结果,使用类型转换操作
*/
//方案一:
public Dog isManyTime(){
System.out.println("养狗");
return new Dog();
}
public Cat isLittleTime(){
System.out.println("养猫");
return new Cat();
}
方案二
public Animal isManyTime(boolean time){
if(time){
System.out.println("养狗");
return new Dog();}
else {
System.out.println("养猫");
return new Cat();
}
}
boolean time=false;
Animal temp;
if(time){
temp= master.isManyTime();//无论返回什么子类类型实例,都可以用父类引用接收,向上转型
} else
temp=master.isLittleTime();
System.out.println(temp);
Animal result=master.isManyTime(time);
/*
同一个操作行为,针对不同参数,返回不同对象实例,完成不同的操作,适用于多态操作
*/