多态
多态是继封装,继承后面向对象的第三大特性
多态是出现在继承或接口实现关系中
多态的定义
是指同一行为,具有多个不同表现形式。
多态前提
- 继承或者实现【二选一】
- 方法的重写【意义体现:不重写,无意义】
- 父类引用指向子类对象【格式体现】
体现格式
父类类型 变量名 = new 子类/实现类构造器;
变量名.方法名;
实现例子
定义父类:
public class Animal {
public void eat(){
System.out.println("动物吃");
}
}
定义子类猫:
public class Cat extends Animal{
@Override
public void eat() {
System.out.println("猫吃鱼");
}
}
定义子类狗:
public class Dog extends Animal{
@Override
public void eat() {
System.out.println("狗吃骨头");
}
}
测试类实现:
public static void main(String[] args) {
// 多态形式,创建对象
Animal a1 = new Cat();
// 调用的是 Cat 的 eat
a1.eat();
// 多态形式,创建对象
Animal a2 = new Dog();
// 调用的是 Dog 的 eat
a2.eat();
}
多态的好处
实际开发的过程中,父类类型作为方法形式参数,传递子类对象给方法,进行方法的调用
引用类型转换
向上转型
多态本身是子类类型向父类类型向上转换(自动转换)的过程,这个过程是默认的。 当父类引用指 向一个子类对象时,便是向上转型。
使用格式
父类类型 变量名 = new 子类类型();
如:Animal a = new Cat();
向下转型(强制转换)
向下转型:父类类型向子类类型向下转换的过程,这个过程是强制的。 一个已经向上转型的子类对象,将父类 引用转为子类引用,可以使用强制类型转换的格式,便是向下转型
使用格式
子类类型 变量名 = (子类类型) 父类变量名;
如:
Aniaml a = new Cat();
Cat c =(Cat) a;
案例
定义父类
public class Animal {
public void eat(){
System.out.println("动物吃");
}
}
定义子类
public class Dog extends Animal{
@Override
public void eat() {
System.out.println("狗吃骨头");
}
public void watch(){
System.out.println("狗看家");
}
}
测试类
public static void main(String[] args) {
Animal a2 = new Dog();
a2.eat();
Dog d1 = (Dog)a2;
d1.watch();
eat(a1);
}
public static void eat(Animal a){
System.out.println("吃饭");
}
转型异常
public class Test {
public static void main(String[] args) {
// 向上转型
Animal a = new Cat();
a.eat(); //调用了cat的eat()方法
Dog d = (Dog)a; //将Cat对象强制转成Dog对象
// 调用的是 Dog 的 watchHouse 【运行报错】
d.watchHouse();
instanceof关键字解决转型异常
变量名 instanceof 数据类型
如果变量属于该数据类型或者其子类类型,返回true。
如果变量不属于该数据类型或者其子类类型,返回false
所以,转换前,我们好先做一个判断,代码如下:
public class Test {
public static void main(String[] args) {
// 向上转型
Animal a = new Cat();
a.eat(); // 调用的是 Cat 的 eat
// 向下转型
if (a instanceof Cat){
Cat c = (Cat)a;
c.catchMouse(); // 调用的是 Cat 的 catchMouse
}else if (a instanceof Dog){
Dog d = (Dog)a;
d.watchHouse(); // 调用的是 Dog 的 watchHouse
}
}
}