对象的多态性

java引用变量有两个类型:

一个是编译时的类型,一个是运行时的类型,

编译时的类型由声明该变量时使用的类型决定,

而运行时的类型由实际赋给变量的对象决定。

如果编译时类型和运行时类型不一致,就会出现所谓的多态(ploymorphism)

 

多态性在面向对象中是一个重要的概念,在java中面向对象主要有一下两种主要体现:

1.方法的重载与覆写。

2.对象的多态性。

对象的多态性主要分为一下两种类型

1、向上转型:子类对象--》父类对象

2、向下转型:父类对象---》子类对象

对于向上转型,程序会自动完成,而对于向下转型时,必须明确致命要转型的子类类型,

【对象转型】

对象向上转型: 父类  父类对象=子类实例;

对象向下转型: 子类  子类对象=(子类)父类实例;

例子:对象向上转型

package test1;

class A {
	public void fun1() {
		System.out.println("A-->public void fun1(){}");
	}

	public void fun2() {
		this.fun1();
	}
}

class B extends A { // B继承A类
	public void fun1() { // B覆写A的fun1方法
		System.out.println("B---> public void fun1(){}");
	}

	public void fun3() {
		System.out.println("B---> public void fun3(){}");
	}
}

public class PolDemo01 {
	public static void main(String args[]) {
		B b = new B(); // 定义子类实现实例化对象
		A a = b;// 发生了向上 转型的关系,子类--->父类
		a.fun1();// 此类方法被子类覆写过
	}
}

  结果:

B---> public void fun1(){}

以上程序就是一个向上转型的关系,从程序的运行结果中可以发现,此时虽然是使用父类对象调用fun1方法,但实际上调用的方法是被子类覆写过的方法,也就是说,如果对象发生了向上转型关系后,所调用的方法一定是被子类覆写过的方法,但是在此时一定要注意,此时的对象a是无法调用B类中的fun3()方法的,因为此方法只在子类定义,而没有在父类中定义,如果要想调用子类自己的方法,则肯定要使用子类实例,随意此时可以将对象进行向下转型:

范例:对象向下转型

package test2;

class A { // 定义父类
	public void fun1() {
		System.out.println("A----> public void fun1(){}");
	}

	public void fun2() {
		this.fun1();
	}
}

class B extends A { // 子类继承父类
	public void fun1() {// 覆写父类的fun1()方法
		System.out.println("B-----> public void fun1(){}");
	}

	public void fun3() {
		System.out.println("B----> public void fun3(){}");
	}
}

public class PolDemo02 {
	public static void main(String[] args) {
		A a = new B();// 发生了向上转型的关系,子类---》 父类
		B b = (B) a;// 此时发生了向下转型关系
		b.fun1();// 调用方法被覆写的方法
		b.fun2();// 调用父类的方法
		b.fun3();// 调用子类自己定义的方法
	}
}

  结果:

B-----> public void fun1(){}
B-----> public void fun1(){}
B----> public void fun3(){}

如果要想调用子类自己的方法,则一定只能用子类声明对象,另外,在子类中调用了父类中的fun2(),fun2()方法要调用fun1()方法,但此时fun1()方法已经被子类所覆写,所以,此时调用的方法是被子类覆写过的方法。

*************************************************************************************

注意:向下转型的要求

在进行对象的向下转型前,必须首先发生对象向上转型,否则将出现对象转换异常。

**************************************************************************************

下面设计一个方法,要求此方法可以接受A类的任意子类对象,并调用方法。此时,如果不实用对象多态性,则肯定不会使用一下形式的代码:

package test1;

class A {
	public void fun1() {
		System.out.println("A--->public void fun1(){}");
	}

	public void fun2() {
		this.fun1();
	}
}

class B extends A {
	public void fun1() {
		System.out.println("B---->public void fun1(){}");
	}
}

class C extends A {
	public void fun1() {
		System.out.println("C---> public void fun1(){}");
	}

	public void fun5() {
		System.out.println("C---->public void fun3(){}");
	}
}

public class PolDemo04 {
	public static void main(String[] args) {
		fun(new B());// 传递B类实例
		fun(new C());// 传递C类实例
	}

	public static void fun(B b) {// 接收子类B的实例
		b.fun1();// 统一调用覆写父类的fun1()方法
	}

	public static void fun(C c) {// 接收子类C的实例
		c.fun1();
	}
}

  结果:

B---->public void fun1(){}
C---> public void fun1(){}

package test2;

class A {
	public void fun1() {
		System.out.println("A---> public void fun1(){}");
	}

	public void fun2() {
		this.fun1();
	}
}

class B extends A {
	public void fun1() {
		System.out.println("B--->public void fun1(){}");
	}

	public void fun3() {
		System.out.println("B--->public void fun3(){}");
	}
}

class C extends A {
	public void fun1() {
		System.out.println("C--->public void fun1(){}");
	}

	public void fun5() {
		System.out.println("C--->public void fun3(){}");
	}
}

public class PolDemo05 {
	public static void main(String[] args) {
		fun(new B());// 传递B类实例,产生向上转型
		fun(new C());// 传递C类实例,产生向上转型
	}

	public static void fun(A a) {// 接收父类对象
		a.fun1();
	}
}

  结果:

B--->public void fun1(){}
C--->public void fun1(){}

在fun()方法中使用了对象的多态性,所以可以接受任何的子类对象,这样无论子类如何增加,fun()方法都不用做任何的改变,

因为一旦发生对象的向上转型关系后,调用的方法一定是被子类覆写过的方法。

posted on 2011-12-06 10:45  wangbokun  阅读(691)  评论(0编辑  收藏  举报

导航