Java中的多态的简单总结
来源:互联网 发布:linux 停止iscsi服务 编辑:程序博客网 时间:2024/05/09 23:32
时间在流逝,春节也快要到了。别的同学都已经在家好多天,自己还在学校继续忙着。要想人前显贵,就得人后受罪,依然记得高中的时候物理老师送给我们的话,虽然有时候感觉很寂寞,但是想想现在的付出是为了以后的美好生活,还是会很有动力。
今天总结面向对象设计中的多态(polymorphism)了,刚开始接触多态这个概念的时候觉得很混乱,随着学习的不断深入,渐渐开始理解这种机制。
- 多态的概念
- 多态的实现机制
- final关键字
一、多态的概念
从字面上理解,多态可以理解为多种形态,多种类型。我们知道,通过继承可以使用父类型(supertype)来引用子类型变量(subtype),也就是说,每个子类对象也可以看做是超类的对象,在程序中可以将多种类型(从同一基类导出的类型)视为同一类型来处理。而同一段代码也就可以毫无差别的运行在不同类型之上了。这些,就是实现多态机制的基础。一个对象变量可以引用多种实际类型的现象被称之为多态。
来看一段代码:
import java.util.*;/** * This program demonstrates inheritance. * @version 1.21 2013/01/25 * @author LiMing */public class ManagerTest{ public static void main(String[] args) { // construct a Manager object Manager boss = new Manager("Carl Cracker", 80000, 1987, 12, 15); boss.setBonus(5000); Employee[] staff = new Employee[3]; // fill the staff array with Manager and Employee objects staff[0] = boss; staff[1] = new Employee("Harry Hacker", 50000, 1989, 10, 1); staff[2] = new Employee("Tommy Tester", 40000, 1990, 3, 15); // print out information about all Employee objects for (Employee e : staff) System.out.println("name=" + e.getName() + ",salary=" + e.getSalary()); }}class Employee{ public Employee(String n, double s, int year, int month, int day) { name = n; salary = s; GregorianCalendar calendar = new GregorianCalendar(year, month - 1, day); hireDay = calendar.getTime(); } public String getName() { return name; } public double getSalary() { return salary; } public Date getHireDay() { return hireDay; } public void raiseSalary(double byPercent) { double raise = salary * byPercent / 100; salary += raise; } private String name; private double salary; private Date hireDay;}class Manager extends Employee{ /** * @param n the employee's name * @param s the salary * @param year the hire year * @param month the hire month * @param day the hire day */ public Manager(String n, double s, int year, int month, int day) { super(n, s, year, month, day); bonus = 0; } public double getSalary() { double baseSalary = super.getSalary(); return baseSalary + bonus; } public void setBonus(double b) { bonus = b; } private double bonus;}
我们可以想象,一个经理Manager必然是一个雇员Employee,经理是子类型,而雇员是父类型。在代码中我们通过
staff[0]=boss; 这条语句将Manager型的引用赋给了Employee类型,在Employee类中拥有一个方法getSalary(),而在Manager中有同样的一个方法getSalary(),程序运行的最后结果我们惊奇的发现,Employee型的对象引用竟然正确的调用了我们希望的Manager的getSalary方法。这个例子作为多态的简单演示,下面我们来讨论多态的实现机制。
二、多态的实现机制
首先我们先了解几个术语:绑定(binding),《Java编程思想》中说“将一个方法调用同一个方法主体关联起来被称作绑定”
。
这句话个人理解是这样的:假设集合A是一个由所有类中的所有的方法组成的方法集合,集合B是由全部的对象以及每个对象所拥有
的动作(方法)组成的集合,当我们程序在出现方法调用的时候,必然是由集合B和集合A中的两个元素进行交互。B中的一个元素调
用A中的方法时,通过一个过程来找到确定的该调用的方法,这个过程被称之为绑定。
在程序执行之前进行的绑定被称之为前期绑定(静态绑定)这是由编译器以及连接程序确定的(至于前期绑定的具体过程还请高手不
吝赐教),在程序运行过程中实现的绑定被称之为后期绑定(动态绑定、运行时绑定)。在Java中所有的方法都是通过动态绑定来实
现多态的
我们主要来研究动态绑定这个概念,首先我们需要区分变量的实际类型(actual type)与声明类型(declared type),我们
知道一个变量必须要被声明为某种类型。请看下面这两句代码:
Employee obj = new Manager();obj.getSalary();
这里obj的声明类型是Employee,一个引用变量可以是一个null值或者是一个对声明类型实例的引用。实例可以是该类型本身或者它
的子类型。变量的实际类型是被变量引用的对象的实际类。在这里obj引用的是Manager类型的变量,所以obj的声明类型是Employee
,实际类型是Manager。当调用getSalary方法时是由obj的实际类型所决定的,因为在程序运行之前我们并不能够确定某个变量将引
用何种类型,所以需要在运行时加以确定,从而调用相应的方法,这就是动态绑定。
我们来看看动态绑定的工作机制:
1>编译器查看对象的声明类型以及方法名。假设调用obj.function(param),且隐式参数obj被声明为C类的对象(C类作为子类来看
待)。需要注意的是:有可能存在多个名字为funciton的,但参数类型不一样的方法。例如可能存在function(int),function
(String)等。编译器会列举C类中的所有名为function的方法和其超类中访问属性为public的且名为function的方法。至此编译器
已经获得了所有可能被调用的候选方法。
2>接下来编译器将查看调用方法时提供的类型参数。如果所有名为function的方法中存在一个与提供的类型参数完全匹配,就选
择这个方法。这个过程被称之为重载解析(overloading resolution)
总之,当程序运行时并且采用动态绑定调用方法时,虚拟机一定调用与obj所引用的对象的实际类型最适合的那个类的方法。假设
obj的实际类型是A,需要调用function(int)型的方法,它是B类的子类,如果A类定义了function(int)方法,就直接调用它;
否则在A类的超类中寻找function(int),以此类推。
我们来看一段代码:
public class DynamicBinding {/** * 演示动态绑定 * @author LiMing * @since 2013/01/25 * @param args */public static void main(String[] args) {// TODO Auto-generated method stubPerson[] p =new Person[3];p[0]=new Person();p[1]=new Student();p[2]=new GraduateStudent();for(Person obj:p)printObject(obj);}public static void printObject(Object o){System.out.println(o.toString());}}class Person{public Person(){}public String toString(){return "This is class Person!";}}class Student extends Person{public Student(){}public String toString(){return "This is class Student!";}}class GraduateStudent extends Student{public GraduateStudent(){}public String toString(){return "This is calss GraduateStudent!";}}
匹配方法的签名和绑定的方法的实现是两个独立的事情。引用变量的声明类型决定了编译时匹配哪个方法。编译器在编译时,会根据类型参数、参数个数和参数顺序找到匹配的方法。一个方法可能在几个子类中都被实现。Java虚拟机在运行是动态绑定的方法的实现,这是由变量的实际类型决定的。
- Java中的多态的简单总结
- [Java]关于Java中的数值计算的简单总结
- java中的多态总结
- Java中的多态总结
- java中的多态总结
- 关于java中的多态的一些小总结
- java 容器的简单总结
- Java简单的一些总结
- java中的继承与多态总结
- java中的基础知识的总结
- 简单总结一下java中的容器----持有对象
- JAVA 内部类的简单总结
- JAVA 内部类的简单总结
- JAVA 内部类的简单总结
- JAVA 内部类的简单总结
- JAVA 内部类的简单总结
- JAVA 内部类的简单总结
- JAVA 内部类的简单总结
- Eclipse背景颜色及字体设置
- Modem协议中对Com口针脚信号的定义与使用
- win2008上的IIS7如何配置远程可以访问共享
- 算法学习笔记----插入排序
- 曾经的美好:再见了,塞班!
- Java中的多态的简单总结
- oracle 列合并到行
- 检测百度关键字网站排名的python 程序
- DCD、DTR、DSR、RTS及CTS等五个状态指示分别代表什么意思?
- Python 文件操作实现代码
- C++ 虚拟函式的妙用 [大三TJB_708]
- 立体视觉算法--SAD+DP
- 如何在MyEclipse Eclipse中显示行数
- 从零开始学习VC++6.0之并口控制(第三课 8位数据端口输出)