论文部分内容阅读
摘要:多态性是面向对象的重要特性之一,Java中的多态体现在类的继承和实现接口等方面。本文就JAVA语言支持的多态性作了深入全面的探讨,在此基础上,结合例子说明了多态性在程序设计中的应用。
关键词:Java语言;多态性; 类;接口
中图分类号:TP311文献标识码:A 文章编号:1009-3044(2007)17-31349-01
An Study on Java’s Dynamic Polymorphism
GAO Wei, LI Shuang
(Tangshan teacher’s college Department of Computer Science,Tangshan 063000,China)
Abstract:Polymorphism is one of the object-oriented characteristic, extending super class and implementing interfaces of a class embodies java's polymorphism. This paper studies polymorphs based on java home and completely, and also discusses the polymorphous application by examples in Java programming.
Key Words:Java Language,Polymorphism,Class,Interface
0 引言
多态(Polymorphism)是面向对象技术的核心概念,按字面意思就是“多种形状”。 它反映了人们在求解问题时,对相似性问题的一种求解方法。在Java语言中,多态性可以通过强制多态、重载多态、重写多态、参数化多态4种形式来表现。重写多态和参数化多态统称为一般多态,一般多态性用来系统地刻画语义上相关的一组类型。重载多态和强制多态统称特殊多态性,特殊多态性刻画语义上无关联的类型间的关系。
在面向对象系统中,多态性特指相同的消息被发送到父类或子类对象上,将导致完全不同的行为。在Java语言中,运行时动态选择调用的方法或对象的机制,正是方法的重写使得多态得以实现。本文就Java语言中的这一多态性及在程序设计中的应用作一个深入全面的探讨。
1 与多态有关的概念
Java语言中与多态有关的概念包括重载(overload)和覆盖(override)。
1.1 重载
重载是指在一个类中,允许定义多个同名的方法,但这些方法的参数数目不同或相同位置上的参数类型不同。对于编译器来说这些同名方法是不同的,因为编译器根据不同的参数列表对同名方法的名称做修饰。例如两个同名方法:int exampleA(int a)和int exampleA(float a),它们的地址在编译期间就已经确定了。就此而言,重载并不是真正的多态。
重载代表着实现类内部一种行为的多种不同的手段,最常见的是在设计类时定义多个构造方法,以满足在不同初始化条件下创建该类的实例对象。
1.2 覆盖
覆盖分两个方面:一是指允许子类定义的成员变量与父类成员变量同名,但值或数据类型不同,此时称子类成员变量隐藏了父类成员变量;二是指允许子类重写父类的某个方法,重写的方法与父类被重写的方法功能不同,但两者具有相同名字,相同参数列表和相同返回类型,但不得提高访问权限。
虽然子类能够通过覆盖把父类的状态和行为改变成自己需要的状态和行为,但是仍可通过关键字super调用父类中的方法及成员变量。子类使用父类的方法,这属于继承性的体现。
从总体上来说,一般多态性是真正的多态性;特殊多态性只是表面的多态性。因为重载只允许某一个符号有多种类型,而它所代表的值分别有不同的、不相兼容的类型。
2 多态的实现
2.1 通过父类对象动态调用子类的方法来实现
如果一个类有很多子类,且这些子类都重写了父类的某个方法来分别产生不同的行为,如何判断所引用对象的实际类型,根据其实际的类型调用其相应的方法?这就涉及到对象的转型问题。Java允许把子类创建的一个对象的引用放到一个父类对象中,此时称该父类对象是子类对象的上转型对象(实际是将子类对象的指针赋值给父类对象的指针)。通过上转型对象调用属于子类的方法时就可能具有多种形态。由于对象是在运行时由其所属的类动态生成的,它所调用的方法将采用动态绑定技术。
虽然上转型对象的实体是子类负责创建的,但上转型对象会失去原来的一些功能。关于上转型对象有如下结论:
1)上转型对象不能操作子类新增的成员变量(失掉了这部分属性),不能调用子类新增的方法。
2)上转型对象可以操作子类继承或隐藏的成员变量,也可以使用子类继承的或重写的方法。
3)上转型对象操作子类继承或重写的方法时,就时通知对应的子类对象去调用这些方法。因此,如果子类重写了父类的某个方法后,对象的上转型对象调用这个方法时,一定是调用了这个重写的方法。
4)可以讲对象的上转型对象再强制转换到一个子类的对象,这时,该子类对象又具备了子类的所有属性和功能。
实例2.1是一个关于多态的测试程序,Sharpe类表示所有形状的基类,其showarea()方法用于输出图形面积,但具体计算由子类决定。目前图形有Circle,表示为Sharpe类的子类。在类Test1中,通过上转型对象调用子类方法实现对不同类别形状面积计算的区别。(本文实例旨在说明多态的正确实现,所有代码已在J2SE v1.5.0下编译并运行通过)
//实例2.1 Test1.java
class Sharpe{
private int x,y;
public Sharpe(int x1,int y1){x=x1;y=y1;}
public void showarea(){ System.out.println("Area of shape is :"+ 0.0);}}
class Circle extends Sharpe{
private int radius;
public Circle(int x,int y, int r){super(x,y);radius=r;}
public void showarea(){
System.out.println("Area of circle is :"+3.14*radius*radius);}
}
public class Test1{
public static void disparea(Sharpe r){r.showarea();}
public static void main(String args[]){
Sharpe r1=new Sharpe(1,1);
Sharpe r2=new Circle(1,1,1);
disparea(r1);
} }
运行结果:
Area of shape is :0.0
Area of circle is :3.14
2.2 通过接口类型变量引用实现接口的类的对象来实现
接口的思想在于它可以规定一个类必须做什么,而不管你如何做。接口中的方法默认为public,这些方法由使用接口的类去全部实现,要求方法的名字、返回类型、参数列表必须与接口中完全一致,且一定要用public修饰。接口把方法定义与类的层次隔离开来,我们可以充分利用多态性“一个接口,多个实现”,使处于不同层次甚至互不相关的类具有相同的行为,并在运行时动态的调用方法。
接口可以作为一种引用类型来使用,可以把任何实现该接口的类创建的对象的引用放到该接口类型的变量中,通过这些变量访问相应类所实现的接口中的方法,Java 运行时,系统会动态地确定应该使用哪个类中的方法。
实例2.2是一个不同类别对象行动的判断程序。公用接口Action派生不相关的两个类,即门类Door 和窗类Window但它们实现相同行为open或close。因此接口可以实现更加灵活多样的多态性。
//实例2.2 Test2.java
interface Action{
void close();
void open();}
class Door implements Action{
public void close(){
System.out.println("Door Close!");}
public void open(){
System.out.println("Door Open!");}
}
class Window implements Action{
public void close(){
System.out.println("Window Close!");}
public void open(){
System.out.println("Window Open!");}
}
public class Test2{
public static void close(Action r){r.close();}
public static void main(String args[]){
Door r1=new Door(); close(r1);
Window r2=new Window(); close(r2);}
}
运行结果:
Door Close!
Window Close!
3 Java语言的多态性的应用
多态的精髓在于提供了同一类对象差异性的处理方法,子类通过多态重写从父类继承的方法来实现子类的差异性。
如果通过父类对象动态调用子类的方法来实现,子类继承于父类,而且子类是相关的。我们把相关子类的公共特性抽象为公共父类,在公共父类中实现一些通用的方法代码,以减少子类中的代码冗余,提高软件的复用性。并且充分利用Java的多态性,让父类的引用指向不同的子类对象,以对外提供相同的服务接口。这种方法的优点是利用抽象方法必须被重写的特性,使一个类的所有子类都表现出相同的对外接口而内部的实现可以各异。但这种相同的服务接口仅限于相关类。
如果通过接口类型变量引用实现接口的类的对象来实现,类之间并不相关,通过实现同一接口而具有了相同行为,体现了更加灵活多样的多态性。接口作为引用类型与实现类型之间的一致约定,比继承更安全、清晰、不存在盲目性。所以,如果不需要为一组类提供公用代码,建议优先考虑使用接口来实现多态。
4 结束语
在Java面向对象的程序设计中有效地利用多态性,可以提高程序的可扩充性、灵活性和程序代码的再用率。本文就Java语言支持的多态性作了全面的探讨,目的在于希望Java程序设计人员能更好地利用多态性,开发高效、灵活、健壮的Java程序。
参考文献:
[1]张孝祥. Java 就业培训教程[M]. 北京: 清华大学出版社,2003.
[2]蓝雯飞.面向对象程序设计语言C++中的多态性[J].微型机与应用,2006(6):11.
[3]耿祥义,张跃平.JAVA2实用教程[M].北京:清华大学出版社,2004.
关键词:Java语言;多态性; 类;接口
中图分类号:TP311文献标识码:A 文章编号:1009-3044(2007)17-31349-01
An Study on Java’s Dynamic Polymorphism
GAO Wei, LI Shuang
(Tangshan teacher’s college Department of Computer Science,Tangshan 063000,China)
Abstract:Polymorphism is one of the object-oriented characteristic, extending super class and implementing interfaces of a class embodies java's polymorphism. This paper studies polymorphs based on java home and completely, and also discusses the polymorphous application by examples in Java programming.
Key Words:Java Language,Polymorphism,Class,Interface
0 引言
多态(Polymorphism)是面向对象技术的核心概念,按字面意思就是“多种形状”。 它反映了人们在求解问题时,对相似性问题的一种求解方法。在Java语言中,多态性可以通过强制多态、重载多态、重写多态、参数化多态4种形式来表现。重写多态和参数化多态统称为一般多态,一般多态性用来系统地刻画语义上相关的一组类型。重载多态和强制多态统称特殊多态性,特殊多态性刻画语义上无关联的类型间的关系。
在面向对象系统中,多态性特指相同的消息被发送到父类或子类对象上,将导致完全不同的行为。在Java语言中,运行时动态选择调用的方法或对象的机制,正是方法的重写使得多态得以实现。本文就Java语言中的这一多态性及在程序设计中的应用作一个深入全面的探讨。
1 与多态有关的概念
Java语言中与多态有关的概念包括重载(overload)和覆盖(override)。
1.1 重载
重载是指在一个类中,允许定义多个同名的方法,但这些方法的参数数目不同或相同位置上的参数类型不同。对于编译器来说这些同名方法是不同的,因为编译器根据不同的参数列表对同名方法的名称做修饰。例如两个同名方法:int exampleA(int a)和int exampleA(float a),它们的地址在编译期间就已经确定了。就此而言,重载并不是真正的多态。
重载代表着实现类内部一种行为的多种不同的手段,最常见的是在设计类时定义多个构造方法,以满足在不同初始化条件下创建该类的实例对象。
1.2 覆盖
覆盖分两个方面:一是指允许子类定义的成员变量与父类成员变量同名,但值或数据类型不同,此时称子类成员变量隐藏了父类成员变量;二是指允许子类重写父类的某个方法,重写的方法与父类被重写的方法功能不同,但两者具有相同名字,相同参数列表和相同返回类型,但不得提高访问权限。
虽然子类能够通过覆盖把父类的状态和行为改变成自己需要的状态和行为,但是仍可通过关键字super调用父类中的方法及成员变量。子类使用父类的方法,这属于继承性的体现。
从总体上来说,一般多态性是真正的多态性;特殊多态性只是表面的多态性。因为重载只允许某一个符号有多种类型,而它所代表的值分别有不同的、不相兼容的类型。
2 多态的实现
2.1 通过父类对象动态调用子类的方法来实现
如果一个类有很多子类,且这些子类都重写了父类的某个方法来分别产生不同的行为,如何判断所引用对象的实际类型,根据其实际的类型调用其相应的方法?这就涉及到对象的转型问题。Java允许把子类创建的一个对象的引用放到一个父类对象中,此时称该父类对象是子类对象的上转型对象(实际是将子类对象的指针赋值给父类对象的指针)。通过上转型对象调用属于子类的方法时就可能具有多种形态。由于对象是在运行时由其所属的类动态生成的,它所调用的方法将采用动态绑定技术。
虽然上转型对象的实体是子类负责创建的,但上转型对象会失去原来的一些功能。关于上转型对象有如下结论:
1)上转型对象不能操作子类新增的成员变量(失掉了这部分属性),不能调用子类新增的方法。
2)上转型对象可以操作子类继承或隐藏的成员变量,也可以使用子类继承的或重写的方法。
3)上转型对象操作子类继承或重写的方法时,就时通知对应的子类对象去调用这些方法。因此,如果子类重写了父类的某个方法后,对象的上转型对象调用这个方法时,一定是调用了这个重写的方法。
4)可以讲对象的上转型对象再强制转换到一个子类的对象,这时,该子类对象又具备了子类的所有属性和功能。
实例2.1是一个关于多态的测试程序,Sharpe类表示所有形状的基类,其showarea()方法用于输出图形面积,但具体计算由子类决定。目前图形有Circle,表示为Sharpe类的子类。在类Test1中,通过上转型对象调用子类方法实现对不同类别形状面积计算的区别。(本文实例旨在说明多态的正确实现,所有代码已在J2SE v1.5.0下编译并运行通过)
//实例2.1 Test1.java
class Sharpe{
private int x,y;
public Sharpe(int x1,int y1){x=x1;y=y1;}
public void showarea(){ System.out.println("Area of shape is :"+ 0.0);}}
class Circle extends Sharpe{
private int radius;
public Circle(int x,int y, int r){super(x,y);radius=r;}
public void showarea(){
System.out.println("Area of circle is :"+3.14*radius*radius);}
}
public class Test1{
public static void disparea(Sharpe r){r.showarea();}
public static void main(String args[]){
Sharpe r1=new Sharpe(1,1);
Sharpe r2=new Circle(1,1,1);
disparea(r1);
} }
运行结果:
Area of shape is :0.0
Area of circle is :3.14
2.2 通过接口类型变量引用实现接口的类的对象来实现
接口的思想在于它可以规定一个类必须做什么,而不管你如何做。接口中的方法默认为public,这些方法由使用接口的类去全部实现,要求方法的名字、返回类型、参数列表必须与接口中完全一致,且一定要用public修饰。接口把方法定义与类的层次隔离开来,我们可以充分利用多态性“一个接口,多个实现”,使处于不同层次甚至互不相关的类具有相同的行为,并在运行时动态的调用方法。
接口可以作为一种引用类型来使用,可以把任何实现该接口的类创建的对象的引用放到该接口类型的变量中,通过这些变量访问相应类所实现的接口中的方法,Java 运行时,系统会动态地确定应该使用哪个类中的方法。
实例2.2是一个不同类别对象行动的判断程序。公用接口Action派生不相关的两个类,即门类Door 和窗类Window但它们实现相同行为open或close。因此接口可以实现更加灵活多样的多态性。
//实例2.2 Test2.java
interface Action{
void close();
void open();}
class Door implements Action{
public void close(){
System.out.println("Door Close!");}
public void open(){
System.out.println("Door Open!");}
}
class Window implements Action{
public void close(){
System.out.println("Window Close!");}
public void open(){
System.out.println("Window Open!");}
}
public class Test2{
public static void close(Action r){r.close();}
public static void main(String args[]){
Door r1=new Door(); close(r1);
Window r2=new Window(); close(r2);}
}
运行结果:
Door Close!
Window Close!
3 Java语言的多态性的应用
多态的精髓在于提供了同一类对象差异性的处理方法,子类通过多态重写从父类继承的方法来实现子类的差异性。
如果通过父类对象动态调用子类的方法来实现,子类继承于父类,而且子类是相关的。我们把相关子类的公共特性抽象为公共父类,在公共父类中实现一些通用的方法代码,以减少子类中的代码冗余,提高软件的复用性。并且充分利用Java的多态性,让父类的引用指向不同的子类对象,以对外提供相同的服务接口。这种方法的优点是利用抽象方法必须被重写的特性,使一个类的所有子类都表现出相同的对外接口而内部的实现可以各异。但这种相同的服务接口仅限于相关类。
如果通过接口类型变量引用实现接口的类的对象来实现,类之间并不相关,通过实现同一接口而具有了相同行为,体现了更加灵活多样的多态性。接口作为引用类型与实现类型之间的一致约定,比继承更安全、清晰、不存在盲目性。所以,如果不需要为一组类提供公用代码,建议优先考虑使用接口来实现多态。
4 结束语
在Java面向对象的程序设计中有效地利用多态性,可以提高程序的可扩充性、灵活性和程序代码的再用率。本文就Java语言支持的多态性作了全面的探讨,目的在于希望Java程序设计人员能更好地利用多态性,开发高效、灵活、健壮的Java程序。
参考文献:
[1]张孝祥. Java 就业培训教程[M]. 北京: 清华大学出版社,2003.
[2]蓝雯飞.面向对象程序设计语言C++中的多态性[J].微型机与应用,2006(6):11.
[3]耿祥义,张跃平.JAVA2实用教程[M].北京:清华大学出版社,2004.