本文主要是介绍(二十一)Java 之多态,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
目录
一. 前言
二. 多态
2.1. 实例入手
2.2. 虚方法
三. 多态的实现方式
四. 课后习题
一. 前言
多态是同一个行为具有多个不同表现形式或形态的能力。
多态性是对象多种表现形式的体现。
比如我们说“宠物”这个对象,它就有很多不同的表达或实现,比如有小猫、小狗、蜥蜴等等。那么我到宠物店说“请给我一只宠物”,服务员给我小猫、小狗或者蜥蜴都可以,我们就说“宠物”这个对象就具备多态性。
接下来让我们通过实例来了解 Java 的多态。
二. 多态
2.1. 实例入手
public interface Vegetarian {}public class Animal {}public class Deer extends Animal implements Vegetarian {}
因为 Deer 类具有多重继承,所以它具有多态性。以上实例解析如下:
- 一个 Deer IS-A(是一个)Animal。
- 一个 Deer IS-A(是一个)Vegetarian。
- 一个 Deer IS-A(是一个)Deer。
- 一个 Deer IS-A(是一个)Object。
在 Java 中,所有的对象都具有多态性,因为任何对象都能通过 IS-A 测试类型和 Object 类。
访问一个对象的唯一方法就是通过引用型变量。
引用型变量只能有一种类型,一旦被声明,引用型变量的类型就不能被改变了。
引用型变量不仅能够被重置为其他对象,前提是这些对象没有被声明为 final。还可以引用和它类型相同的或者相兼容的对象。它可以声明为类类型或者接口类型。
当我们将引用型变量应用于 Deer 对象的引用时,下面的声明是合法的:
Deer d = new Deer();
Animal a = d;
Vegetarian v = d;
Object o = d;
所有的引用型变量 d、a、v、o 都指向堆中相同的 Deer 对象。
2.2. 虚方法
我们将介绍在 Java 中,当设计类时,被重写的方法的行为怎样影响多态性。
我们已经讨论了方法的重写,也就是子类能够重写父类的方法。
当子类对象调用重写的方法时,调用的是子类的方法,而不是父类中被重写的方法。
要想调用父类中被重写的方法,则必须使用关键字 super。
/* 文件名 : Employee.java */
public class Employee {private String name;private String address;private int number;public Employee(String name, String address, int number) {System.out.println("Constructing an Employee");this.name = name;this.address = address;this.number = number;}public void mailCheck() {System.out.println("Mailing a check to " + this.name+ " " + this.address);}public String toString() {return name + " " + address + " " + number;}public String getName() {return name;}public String getAddress() {return address;}public void setAddress(String newAddress) {address = newAddress;}public int getNumber() {return number;}
}
假设下面的类继承 Employee 类:
/* 文件名 : Salary.java */
public class Salary extends Employee {private double salary; // Annual salarypublic Salary(String name, String address, int number, double salary) {super(name, address, number);setSalary(salary);}public void mailCheck() {System.out.println("Within mailCheck of Salary class ");System.out.println("Mailing check to " + getName()+ " with salary " + salary);}public double getSalary() {return salary;}public void setSalary(double newSalary) {if (newSalary >= 0.0) {salary = newSalary;}}public double computePay() {System.out.println("Computing salary pay for " + getName());return salary / 52;}
}
现在我们仔细阅读下面的代码,尝试给出它的输出结果:
/* 文件名 : VirtualDemo.java */
public class VirtualDemo {public static void main(String[] args) {Salary s = new Salary("Mohd Mohtashim", "Ambehta, UP", 3, 3600.00);Employee e = new Salary("John Adams", "Boston, MA", 2, 2400.00);System.out.println("Call mailCheck using Salary reference --");s.mailCheck();System.out.println("\n Call mailCheck using Employee reference--");e.mailCheck();}
}
运行结果:
Constructing an Employee
Constructing an Employee
Call mailCheck using Salary reference --
Within mailCheck of Salary class
Mailing check to Mohd Mohtashim with salary 3600.0Call mailCheck using Employee reference--
Within mailCheck of Salary class
Mailing check to John Adams with salary 2400.0
例子中,我们实例化了两个 Salary 对象。一个使用 Salary 引用 s,另一个使用 Employee 引用。
编译时,编译器检查到 mailCheck() 方法在 Salary 类中的声明。
在调用 s.mailCheck() 时,Java 虚拟机(JVM)调用 Salary 类的 mailCheck() 方法。
因为 e 是 Employee 的引用,所以调用 e 的 mailCheck() 方法则有完全不同的结果。
当编译器检查 e.mailCheck() 方法时,编译器检查到 Employee 类中的 mailCheck() 方法。
在编译的时候,编译器使用 Employee 类中的 mailCheck() 方法验证该语句, 但是在运行的时候,Java 虚拟机(JVM)调用的是 Salary 类中的 mailCheck() 方法。
该行为被称为虚拟方法调用,该方法被称为虚拟方法。
Java 中所有的方法都能以这种方式表现,借此,重写的方法能在运行时调用,不管编译的时候源代码中引用变量是什么数据类型。
三. 多态的实现方式
方式一:重写
这个内容已经在上一章节详细讲过,就不再阐述,详细可访问:《(二十)Java 面向对象之重载(Overload)与重写(Override)》。
方式二:接口
- 生活中的接口最具代表性的就是插座,例如一个三接头的插头都能接在三孔插座中,因为这个是每个国家都有各自规定的接口规则,有可能到国外就不行,那是因为国外自己定义的接口类型。
- Java 中的接口类似于生活中的接口,就是一些方法特征的集合,但没有方法的实现。
方式三:抽象类和抽象方法
将在下一篇博文中介绍。
四. 课后习题
1. 编写程序实现乐手弹奏乐器。乐手可以弹奏不同的乐器从而发出不同的声音。
2. 编写程序实现主人喂养宠物和跟宠物玩耍的场景。定义宠物类 Pet,宠物都需要吃东西,跟主人玩。定义狗类 Dog、猫类 Cat、Dolphin 海豚类继承 Pet 宠物类。狗狗吃骨头、猫咪吃老鼠、海豚吃乌贼。
3. 写三个具体的类(猫、狗、羊),它们都是动物类的子类,并重写父类的成员方法。编写测试类,随机产生三种具体动物,调用叫声这个方法。
4. 豆豆家养了两只家禽 Poultry:一只鸡 Chicken 和一只鸭 Duck。请再写一个类 Master,有一个方 cry()。
这篇关于(二十一)Java 之多态的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!