首页 > 编程语言 > 详细

JAVA面向对象三大特征之多态

时间:2020-11-03 19:11:27      阅读:32      评论:0      收藏:0      [点我收藏+]

1. 什么是多态?

多态是继封装、继承之后,面向对象的第三大特性,指的是一类事物的行为具有多种形态。

生活中,比如跑的动作,小猫、小狗和大象,跑起来是不一样的。再比如飞的动作,昆虫、鸟类和飞机,飞起来也 是不一样的。可见,同一行为,通过不同的事物,可以体现出来的不同的形态。多态,描述的就是这样的状态。

多态实现的前提:

  • 继承或者实现
  • 子类需重写父类的方法(不重写,多态则无意义)
  • 父类引用指向子类对象(多态实现的格式)

2. 多态的使用

Java代码中使用多态的格式:

父类类型 变量名 = new 子类对象; //父类类型:指子类对象继承的父类类型,或者实现的父接口类型。
变量名.方法名();

我们先定义一个父类

public abstract class Animal {
	public abstract void eat();
}

然后定义两个子类实现父类的eat方法

class Cat extends Animal {
    public void eat() {
    	System.out.println("吃鱼");
    }
}
class Dog extends Animal {
    public void eat() {
    	System.out.println("吃骨头");
    }
    public void watch() {
    	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();
    a2.watch(); // 编译报错
}

由输出结果可知,当使用多态方式调用方法时,首先检查父类中是否有该方法,如果没有,则编译错误;如果有,执行的是子类重写后的方法。

3. 多态的好处

我们看下面的一个例子:

public static void main(String[] args) {
    // 多态形式,创建对象
    Cat c = new Cat();
    Dog d = new Dog();
    // 调用showCatEat
    showCatEat(c);
    // 调用showDogEat
    showDogEat(d);
    /*
    以上两个方法, 均可以被showAnimalEat(Animal a)方法所替代
    而执行效果一致
    */
    showAnimalEat(c);
    showAnimalEat(d);
}
public static void showCatEat (Cat c){
	c.eat();
}
public static void showDogEat (Dog d){
	d.eat();
}
public static void showAnimalEat (Animal a){
	a.eat();
}

由上面的例子我们可以知道,当把父类类型作为方法形式参数,子类对象作为实际参数传递给方法,方法体内调用的是子类重写父类的那个方法(假如子类没有该方法,则调用父类本身的方法)。

利用多态的这个特性,不管Animal有多少个子类,只要该子类重写了父类的eat方法,都可以调用showAnimalEat方法来展示,而不需要每新增一个子类,都要创建一个showXXXEat方法。所以多态的好处就是可以使程序 编写更简单,更易于扩展。

4. 使用多态容易出现的问题

在使用多态的过程中,我们常常会遇到下面代码所示的问题。

public static void main(String[] args) {
    // 向上转型
    Animal a = new Cat();
    a.eat(); // 调用的是 Dog 的 eat
    // 向下转型
    Dog d = (Dog)a;// 运行时会报错
    d.watch(); 
}

这段代码可以通过编译,但是运行时,却报出了 ClassCastException 类型转换异常!这是因为,我们虽然创建的是Cat类型对象,但是a属于父类Animal的引用,编译器编译时并不知道c的具体类型,所以编译时期强制转换成Dog时没有报错。而运行时,虚拟机已经识别出a是Cat对象,Cat和Dog这两个类型并没有任何继承关系,不符合类型转换的定义,此时强制转换自然会报ClassCastException 异常。

为了避免ClassCastException的发生,Java提供了 instanceof 关键字,给引用变量做类型的校验,格式如下:

变量名 instanceof 数据类型
如果变量属于该数据类型,返回true。
如果变量不属于该数据类型,返回false。

所以,转换前,我们最好先做一个判断,代码如下:

public static void main(String[] args) {
    // 向上转型
    Animal a = new Cat();
    a.eat(); // 调用的是 Cat 的 eat
    // 向下转型
    if (a instanceof Cat){
        Cat c = (Cat)a;
        c.eat(); // 调用的是 Cat 的 eat
    } else if (a instanceof Dog){
        Dog d = (Dog)a;
        d.watch(); // 调用的是 Dog 的 watch
    }
}

JAVA面向对象三大特征之多态

原文:https://www.cnblogs.com/linfuxian/p/13921089.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!