1.1 概述
多态按字面的意思就是“多种状态”,通过不同的事物,可以体现出来的不同的形态。多态,描述的就是这样的状态。
1.2 多态的体现
前提
1、必须存在继承或实现的关系
2、子类或实现类必须重写父类方法
3、父类引用指向子类对象(向上转型)
定义格式:
父类类型 变量名 = new 子类对象;
变量名.方法名();
Fu f = new Zi();
f.method();
1.父类有的方法,都可以调用,如果被子类重写了,则会调用子类的方法。
2. 父类没有的方法,而子类存在,则不能调用。
3. 向上转型只对方法有影响,对属性没影响。属性不存在重写。
1.3多态的好处
实际开发的过程中,用于参数统一化,可以使用父类的类型作为方法形参,传递子类对象给方法,进行方法的调用,提高了代码的扩展性
/**
* 父类
*/
public abstract class Animal {
public abstract void ();
}
/**
* 子类
*/
public class Dog extends Animal{
/**
* 子类重写父类方法
*/
@Override
public void run() {
System.out.println("我是一只小狗,喜欢被溜");
}
}
public class Cat extends Animal{
/**
* 子类重写父类方法
*/
@Override
public void run() {
System.out.println("我是一只小猫,不喜欢被溜");
}
}
/**
* 测试类
*/
public class Test {
public static void main(String[] args) {
// 多态形式,创建对象
Cat c = new Cat();
Dog d = new Dog();
showAnimal(c);
showAnimal(d);
public static void showAnimal(Animal animal ){
animal .eat();
}
}
}
// 输出结果: 我是一只小狗,喜欢被溜
// 我是一只小猫,不喜欢被溜
当run方法执行时,执行的是子类重写的方法,在扩展性方面,无论之后再多的子类出现,直接使用showAnimal方法即可。
1.4 向下转型
为什么要发生向下转型?当父类需要调用子类的特有方法,才需要向下转型。
定义格式:
子类 子类对象 = (子类)父类实例
Zi zi = (Zi) fu;
/**
* 父类
*/
public abstract class Animal {
public abstract void ();
}
/**
* 子类
*/
public class Dog extends Animal{
/**
* 子类重写父类方法
*/
@Override
public void run() {
System.out.println("我是一只小狗,喜欢被溜");
}
public void watchHouse() {
System.out.println("看家");
}
}
public class Cat extends Animal{
/**
* 子类重写父类方法
*/
@Override
public void run() {
System.out.println("我是一只小猫,不喜欢被溜");
}
public void catchMouse() {
System.out.println("抓老鼠");
}
}
/**
* 测试类
*/
public class Test {
public static void main(String[] args) {
Animal animal = new Cat();
Cat c = (Cat) animal;
c.catchMouse();
}
}
// 输出结果: 抓老鼠
类转换异常
public class Test {
public static void main(String[] args) {
// 向上转型
Animal a = new Cat();
// 向下转型
Dog d = (Dog)a;
d.watchHouse();
}
}
这段代码可以通过编译,但是运行时,却报出了 ClassCastException ,类型转换异常,这是因为Cat类型对象,运行时不能转换成Dog对象的。这两个类型并没有任何继承关系,不符合类型转换的定义。
为了避免ClassCastException的发生,Java提供了 instanceof 关键字,测试它左边的对象是否是它右边的类的实例,返回 boolean 的数据类型。
public class Test {
public static void main(String[] args) {
// 向上转型
Animal a = new Cat();
// 向下转型
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
}
}
}