1、什么是多态
多态是对象具有多种表现形式的能力。
在面向对象语言中,接口的多种不同的实现方式即为多态。
多态性的科学解释:允许你将父对象设置成为一个或更多的他子对象的技术,赋值之后,父对象就可以根据当前赋值给它的子对象的特性以不同的方式运作。
通俗的解释,就是一句话:可以把一个子类的对象转换为父类的对象。
在Java中,所有的Java对象是多态的,因为任何对象都可以设置为自己本身的类和Object类(Object是所有类的父类)。
了解跟多继承看这里:java类的继承有什么意义
2、如果表现多态
让我们来看一个例子。
例子:
public interface Vegetarian{}
public class Animal{}
public class Deer extends Animal implements Vegetarian{}
现在,Deer类被认为是多态的,因为这有多重继承。于是:
- 鹿is-a动物(is-a等于继承,了解更多is-a看这里:is-a,has-a,like-a是什么)
- 鹿like-a素食(is-a等于实现)
- 鹿 is-a Object
由于多态性,下面的声明是合法的:
Deer d = new Deer();
Animal a = d;
Vegetarian v = d;
Object o = d;
所有d的参考变量d,a,v,o在堆中都指向相同的Deer对象。
了解更多引用传递看这里:
了解更多变量内存存储看这里:
3、方法多态是什么
我们知道方法覆盖,其中一个子类可以在其父覆盖的方法。即覆盖方法的本质是隐藏父类方法,除非子类使用的重载方法中的super关键字。无论子类以何种形态被声明,都会执行子类的方法,这就是方法的多态。
了解更多覆盖看这里:java中覆盖是什么
了解更多重载和覆盖的区别看这里:java中重载和覆盖有什么关系
例如:
/* File name : 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;
}
}
Salary类继承Employee类,如下所示:
/* File name : Salary.java */
public class Salary extends Employee
{
private double salary; //Annual salary
public 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;
}
}
测试代码:
/* File name : 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("
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.0
Call mailCheck using Employee reference–
Within mailCheck of Salary class
Mailing check to John Adams with salary 2400.0
结论如下:
1. 在调用s.mailCheck()时,调用Salary类中的mailCheck()。
2. 在调用e.mailCheck()时,由于e是Salary对象的一个引用,所以实际调用的是Salary类中的mailCheck()。
3. 这种调用被称为虚拟方法调用,该方法被称为虚拟方法。
原文地址:http://blog.csdn.net/ooppookid/article/details/51220407