java面向对象(下)-- 多态

多态概述

  在设计一个方法时,通常希望该方法具备一定的通用性。例如要实现一个动物叫的方法,由于每种动物的叫声是不同的,因此可以在方法中接收一个动物类型的参数,当传入猫类对象时就发出猫类的叫声,传入犬类对象时就发出犬类的叫声。在同一个方法中,这种由于参数类型不同而导致执行结果各异的现象就是多态。

  在java中为了实现多态,允许使用一个父类类型的变量来引用一个子类类型的对象,根据被引用子类对象特征的不同,得到不同的允许结果。

  方法的重载和方法的重写都是java多态性的不同表现,二者一个是编译时的多态,一个是运行时的多态,当然二者的区别并不局限如此,这里就不一一赘述。

多态存在的三个必要条件

  • 继承
  • 重写
  • 父类引用指向子类对象 

以下是一个多态实例的演示,详细说明请看注释:

 1 //定义了接口Animal
 2  interface Animal {
 3      //定义抽象方法
 4      void shout();
 5 }
 6 //定义了Cat类并实现了Animal接口
 7 class Cat implements Animal{
 8     //实现shou()方法
 9     public void shout() {
10         System.out.println("喵喵喵.....");
11     }
12 }
13 //定义了Dog类并实现了Animal接口
14 class Dog implements Animal{
15     //实现shout()方法
16     public void shout() {
17         System.out.println("汪汪汪.....");
18     }
19 }
20 //定义测试类
21 class Example {
22      //定义静态的animalShout()方法,接收一个Animal类型的参数
23     public static void  animalShout(Animal an){
24         an.shout();
25     }
26     public static void main(String[] args) {
27         Animal an1 = new Cat(); //创建Cat对象,使用Animal类型的变量an1来引用
28         Animal an2 = new Dog(); //创建Dog对象,使用Animal类型的变量an2来引用
29         animalShout(an1); //调用animalShout()方法,将an1作为参数插入
30         animalShout(an2); //调用animalShout()方法,将an2作为参数插入
31     }
32  }

 运行结果:

   多态不仅解决了方法同名的问题,而且还使程序变得更加灵活,从而有效地提高程序的可扩展性和可维护性。

多态的优点

  • 1. 消除类型之间的耦合关系

  • 2. 可替换性

  • 3. 可扩充性

  • 4. 接口性

  • 5. 灵活性

  • 6. 简化性

对象的类型转换

  在多态的学习中,涉及到将子类对象当做父类类型使用的情况,例如上面的:

  将子类对象当做父类使用时不需要任何显示地声明,但此时不能通过父类变量去调用子类中的某些方法。

 1 //定义了接口Animal
 2  interface Animal {
 3      //定义抽象方法
 4      void shout();
 5 }
 6 //定义了Cat类并实现了Animal接口
 7 class Cat implements Animal{
 8     //实现shout()方法
 9     public void shout() {
10         System.out.println("喵喵喵.....");
11     }
12     //定义sleep()方法
13     void sleep(){
14         System.out.println("猫在睡觉....");
15     }
16 }
17 
18 //定义测试类
19 class Example {
20      //定义静态的animalShout()方法,接收一个Animal类型的参数
21     public static void  animalShout(Animal animal){
22         animal.shout();//调用传入参数animal的shout()方法
23         animal.sleep();//调用传入参数animal的sleep()方法
24 
25     }
26     public static void main(String[] args) {
27         Cat cat = new Cat(); //创建Cat类的实例化对象
28         animalShout(cat);//调用animalShout()方法,将cat作为参数传入
29 
30     }
31  }

运行结果:

   在main方法中,调用animalShout()方法时传入了参数Cat类型的对象,而方法的参数类型为Animal类型,这便将Cat对象当做父类Animal类型使用,当编译器编译时,发现Animal类中没有定义sleep()方法,从而出现错误,提示找不到sleep()方法。

解决方法:通过强制类型转换将Animal类型的变量强转为Cat类型

 运行结果:

 

   将传入的对象有Animal类型转换为Cat类型后,程序可以成功调用shout()方法和sleep()方法。

  需要注意的是,在进行类型转换时也可能出现错误,例如在animalShout()方法时传入一个Dog类型的对象,这时进行强制类型转换就会出现错误。

 1 //定义了接口Animal
 2  interface Animal {
 3      //定义抽象方法
 4      void shout();
 5 }
 6 //定义了Cat类并实现了Animal接口
 7 class Cat implements Animal{
 8     //实现shout()方法
 9     public void shout() {
10         System.out.println("喵喵喵.....");
11     }
12     //定义sleep()方法
13     void sleep(){
14         System.out.println("猫在睡觉....");
15     }
16 }
17 //定义了Dog类并实现了Animal接口
18 class Dog implements Animal{
19     //实现shou()方法
20     public void shout() {
21         System.out.println("汪汪汪.....");
22     }
23 }
24 //定义测试类
25 class Example {
26      //定义静态的animalShout()方法,接收一个Animal类型的参数
27     public static void  animalShout(Animal animal){
28         Cat cat =(Cat) animal;//将animal类型强转为Cat类型
29         cat.shout();//调用cat的shout()方法
30         cat.sleep();//调用cat的sleep()方法
31 
32     }
33     public static void main(String[] args) {
34         Dog dog = new Dog(); //创建Dog类的实例化对象
35         animalShout(dog);//调用animalShout()方法,将cat作为参数传入
36 
37     }
38  }

运行结果:

   在调用animalShout()方法时,传入一个Dog对象,在强制类型转换时,Animal类型的变量无法强转为Cat类型。

  针对这种情况,java提供了一个关键字instanceof,它可以判断一个对象是否为某个类(或接口)的实例或者子类实例,语法格式如下:

    对象(或者对象引用变量) instanceof 类(或接口)

接下来对animalShout()方法进行修改

 运行结果:

   使用instanceof关键字判断animalShout()方法中传入的对象是否为Cat类型,如果是Cat类型就进行强制类型转换,否则就会打印“this animal is not a cat”。

 ps:个人学习笔记!!!

原文地址:https://www.cnblogs.com/wx60079/p/13410450.html