Java进阶 ---- 多态(Polymorphism)_JAVA_编程开发_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 编程开发 > JAVA > Java进阶 ---- 多态(Polymorphism)

Java进阶 ---- 多态(Polymorphism)

 2011/9/9 8:14:46  瘋叻ハ.兩  http://949507869-qq-com.iteye.com  我要评论(0)
  • 摘要:从前面的继承(Inheritance)到比较this和super,所用的例子都夹杂着多态(Polymorphism)的味道。所以,这篇就是阐述个人总结的多态(Polymorphism)多态,并没有关键字,可以视之为Java的三大特性之一,也可以视为继承“isa”的另一阐述“substitutionprinciple(代理准则)”的体现。在Java中,对象变量(引用变量)是多态的,如:Employeee;//e为对象变量e=newEmployee(...);e=newManager(....)
  • 标签:Java

????? 从前面的继承(Inheritance)到比较this和super,所用的例子都夹杂着多态(Polymorphism)的味道。所以,这篇就是阐述个人总结的多态(Polymorphism)

?

????? 多态,并没有关键字,可以视之为Java的三大特性之一,也可以视为继承“is a”的另一阐述“substitution principle(代理准则)”的体现。在Java中,对象变量(引用变量)是多态的,如:

Employee e;    // e为对象变量
e = new Employee(...);
e = new Manager(....);

????? 变量是多态的,但是还有有些规律可循的,那就是父类的对象变量既可以指向父类实例,也可以指向子类实例,但是子类的对象变量只能指向子类实例

????? 相关代码

package com.PolymorphismTest;

/**************************************************
 * simply introduce something about basic polymorphism,群:152380972                                               
 * @author:      瘋叻ハ.兩                                                                              
 * @revision:    1.0                                                        
 * @create-time: 2011-9-6 下午06:30:33                                               
 ***************************************************/
public class PolymorphismTest1 {
	
	public static void main(String[] args){
		// create arrays Employee
		Employee1[] e1 = new Employee1[2];
		
		// create a manager object
		Manager1 boss = new Manager1("John", 8000, 500);
		
		// it's correct for superclass object to refer subclass object or its'object
		e1[0] = boss;
		e1[1] = new Employee1("Kevin", 4500);
		
		// it's wrong for subclass object refers to superclass object
		// Manager1 m = e1[1];
		
		// e1[i] was considered to be only an Employee1 object by the compiler(编译器)
		e1[0].getSalary();
		// e1[0].setBonus();	// won't work
		
		for(Employee1 e : e1){
			System.out.println(e.getName() + "的工资是:" + e.getSalary());
		}
	}
}

class Employee1{
	
	private String name;
	private int salary;
	
	// default constructor
	public Employee1(){
		
	}
	
	// constructor with fields
	public Employee1(String n, int s){
		name = n;
		salary = s;
	}

	public String getName() {
		return name;
	}

	public int getSalary() {
		return salary;
	}
	
}

class Manager1 extends Employee1{
	
	private int bonus;
	
	public Manager1(String n, int s, int b){
		super(n, s);
		this.bonus = b;
	}
	
	// override method getSalary
	@Override
	public int getSalary(){
		int baseSalary = super.getSalary();
		return  baseSalary + bonus;
	}
}
?

??????运行结果:???

?????????????????? John的工资是:8500
?????????????????? Kevin的工资是:4500

?

????????分 析? :且看下文

?

????? 从上面程序的结果,我们会有这样的疑惑,编译时都是是Employee1类型的变量,为什么结果不是“8000,4500”而是“8500,4500”呢? 答案就是方法的动态绑定(Dynamic Binding),多态的表现形式。简单的说,Java中的对象变量有2中:编译类型运行类型。编译类型由声明该变量使用的类型决定,运行类型由实际赋给该变量的对象决定。当执行至e1[0].getSalary( )时,因为e1[0]指向boss,而boss是Manager1类型,所以此时的getSalary( )方法是Manager1中的。下面代码希望助你理解编译类型和运行类型。

??????相关代码

package com.PolymorphismTest;

/**************************************************
 * differentiate from compiled type and running type,群:152380972                                               
 * @author:      瘋叻ハ.兩                                                                              
 * @revision:    1.0                                                        
 * @create-time: 2011-9-6 下午08:04:15                                               
 ***************************************************/
public class TypeTest {

	public static void main(String[] args) {

		// declare the Animal object 
		Animal a = new Lion();
		
		// print the actual class of a
		System.out.println(a.getClass());
		
		// use photo 1 to identify what compiled type the variable is
		a.run();
	}

}

class Animal{
	// what does it work?
	// in fact, a's compiled type is Animal. when program is compiled, "a.run()" use this method not Lion's 
	public void run(){
		System.out.println("Animal can run!");
	}
}

class Lion extends Animal{
	
	@Override
	public void run(){
		System.out.println("Lion is running...");
	}
}

????? 运行结果:?

?????????????????? class com.PolymorphismTest.Lion
???????????????????Lion is running...

?

???????? 分? 析 :看代码注释

?

?????

????? 关于Animal处的代码注释如果意思不懂,且看多态方法调用的4步曲,知道的可忽视而过。(选自Java核心技术卷1:基础知识)以【 x.f(param) x是C类,x的子类是D类 】为例:

????? 1、根据对象编译类型确定方法名。 编译器首先找的是对象的声明类型和方法名称。所以可以通过x的类型排除其他类型的f方法。但是不能排除f的重载方法,即不同参数类型的同一方法。在本例中,编译器以C类型排除非C类型的f方法,而不是D

?

??????2、根据形参类型名确定具体方法名。 根据传入的形参类型查找相应的方法就能确定具体是哪个方法了,这个过程也称为“overloading resolution”。

?

????? 3、根据修饰词确定绑定状态。? 如果方法被private、static、final修饰,那么这些方法就是static binding,否则是dynamic binding。

?

????? 4、根据绑定状态执行方法体。?当方法是dynamc binding,虚拟机会找到方法执行者的指向类型,即运行类型。如果运行中有同名方法,则执行该方法的方法体,否则执行父类中的方法体。在本例中,如果D类中有f方法,便执行D类的方法,否则执行C类的f方法。当方法是static binding,在多态中是没有意义的,所以就不介绍了

?

?

????? 多态,其实就是对象变量的多态,它的表现形式就是控制方法。可以发现,它的成立条件就是有继承关系。所以说,多态也是继承“is a”的另一阐述“substitution principle(代理准则)”的体现!

?

????? 事后补充,请原谅我的疏忽

????? 对象变量的多态,并不影响到属性的访问,即通过引用变量访问其包含的实例属性时,系统总是访问其编译时类所定义的属性,而不是它运行时类所定义的属性。

????? 相关代码

/**************************************************
 * whether polymorphism influence to access attribute! 群:152380972                                               
 * @author:      瘋叻ハ.兩                                                                              
 * @revision:    1.0                                                        
 * @create-time: 2011-9-7 上午12:07:06                                               
 ***************************************************/
public class TypeTest1 {

	public static void main(String[] args) {

		Animal1 a1 = new Lion1();
		System.out.println("名称是:" + a1.name);
	}

}

class Animal1{
	public String name = "动物";
}

class Lion1 extends Animal1{
	public String name = "Lion";
}

?

??????运行结果

???????????????????? 名称是:动物

?

??????? 分??析? :对象变量的多态不影响属性的访问

?

?

  • 大小: 12.1 KB
  • 查看图片附件
发表评论
用户名: 匿名