李斌,王睿
(扬州市职业大学信息工程学院,江苏扬州225002)
在经历了以大型机为代表的集中计算模式和以PC机为代表的分散计算模式之后,互联网的出现使得计算模式进入了网络计算时代。网络计算模式的一个特点是计算机是异构的,即计算机的类型和操作系统是不一样的,例如SUN工作站的硬件是SPARC体系,软件是Unix中的Solaris操作系统,而PC机的硬件是Intel体系,操作系统是windows或者是Linux。网络计算模式的另一个特点是代码可以通过网络在各种计算机上进行迁移,这就迫切需要一种跨平台的编程语言,使得用它编写的程序能够在网络中的各种计算机上能够正常运行,Java就是在这种需求下应运而生的。Java语言具有简单、面向对象、健壮、安全、可靠、平台无关性、解释执行、多线程、高性能、易学、适用于网络等显著特点,已成为当今最流行的网络编程语言之一。
Java的所有程序都具有封装性、继承性和多态性。封装性就是把对象的属性和服务结合成一个独立的相同单位,并尽可能隐蔽对象的内部细节;继承是软件重用的一种形式,也是自动地实现方法和数据共享的机制;多态性是指在父类中定义的属性或服务被子类继承之后,可以具有不同的数据类型或表现出不同的行为。本文仅就Java的继承性进行一定的探讨。
继承是一种由已有类创建新类的机制。继承也是面向对象语言的基本要素之一,它是源自类的泛化机制,这种抽象机制提供了一种无限重复利用程序资源的途径,继承可以扩展原有的代码,应用到其他程序中,而不必重新编写这些代码,这样不仅节省程序开发时间,而且为未来程序设计增添了新的资源。对象通过继承,保证了实现部分紧内聚和松耦合的良好特性。
利用继承,我们可以先创建一个共有属性的一般类,根据该类再创建具有特殊属性的新类。在Java语言中,通常我们称被继承的一般类为父类(superclass,也叫超类),由继承而得到的特殊类称为子类 (subclass)。我们也可以说子类是由父类派生出的类。
Java的继承原则如下:
1)子类继承父类的成员变量,包括实例成员变量和类成员变量;
2) 子类继承父类除构造方法以外的成员方法,包括实例成员方法和类成员方法;
3)子类不能继承父类的构造方法,因为父类构造方法创建的是父类对象,子类必须声明自己的构造方法,创建子类自己的对象;
4)子类不能删除父类成员;
5)子类可以增加自己的成员变量和成员方法;
6)子类可以重定义父类成员。
在这段代码中,子类 SubA继承了父类SuperA,那么子类自然就拥有了父类的变量a,同时子类自己又添加了自己新的成员变量b以扩充自己的功能。在子类SubA中还可以更改父类SuperA的变量a,让其适应自己的需求,比如,我们在SubA中增加一行代码:int a=3;,这样在子类SubA中的变量a实际上隐藏了父类SuperA的变量a。但是,如果试图在子类SubA中删除父类SuperA的变量a,这是Java所不允许的。
子类的对象即是父类的对象。反之不然,父类的对象不是它的子类对象。例如:SuperA supa=new SubA();这条语句是语法允许的,父类对象supa能够被赋值为子类对象new SubA();而SuBA suba=new SuperA();这条语句编译是不能通过的,因为子类对象suba是不能能够被赋值为父类对象new SuperA()的。
子类直接上一层的父类称为直接父类,如果一个类只有一个直接父类则称这样的继承为单重继承,一个类也可以是多个直接父类的子类,它从多个父类中继承了属性与服务,这样的继承称为多重继承。
在单重继承方式下,父类与子类是一对多的关系,一个子类只有一个直接父类,但一个父类可以有多个子类,每个子类又可以作为父类再有自己的子类。
Java只支持单重继承机制,不支持多重继承,单重继承使得Java结构简单,层次清楚,更安全可靠,从而避免了C++中因多重继承而引起的难以预测的错误。所以声明的类只能有一个父类。子类的声明格式为: [<修饰符>]class<子类名>extends<超类名>,从中我们也能清楚看出Java中类的继承关系为单重继承关系。在Java中,一个父类可以有多个子类,每个子类又可以作为父类再有自己的子类。由此形成具有树形结构的层次体系,其中具有继承关系的、相距多个层次的类之间称为祖先类和后代类,父类也称为直接祖先类。这种树形继承关系并不违反Java的单重继承原则。
其实,在Java中,每个类都有父类,如果没有显式地标明类的父类,则隐含地假设超类为语言包java.lang中说明的Object类。
在Java中,子类对象对父类成员的访问权限主要依据如下规则进行:
1)子类对父类的私有成员(private)没有访问权限;
2)子类对父类的公有成员(public)和保护成员(protected)具有访问权限;
3)子类对父类中缺省权限成员(default)的访问分为两种情况,对同一包中父类的缺省权限成员具有访问权限,而对不同包中父类的缺省权限成员则没有访问权限。
Java只支持单重继承机制,但是实际应用中有时候也需要使用多重继承这个功能。
Java中关于接口实现的声明格式为: [<修饰符>] class<类名> [extends<超类名>] [implements<接口名1>,<接口名2>,…],从中我们可以看出一个类通过关键字implements实现了一系列的接口,这实际上就变相地完成了多重继承的功能,所以通常我们说Java只支持单重继承,不支持多重继承,但是却可以通过接口来实现多重继承的功能。
问题在于Java中接口本身的继承关系是单重继承还是多重继承呢?我们在学习接口的时候知道,编译的时候接口会像类一样被编译,所以很多人就非常简单地认为接口既然被当成类编译,那么自然接口的继承性也和类一样是单重的,这也正好和Java的单重继承原则不谋而合。事实上这样的理解是完全错误的,恰恰相反,接口的本身的继承性却是多重的。我们看下面一段程序(程序名为ClassABCTest.java):
程序能正常编译,运行结果为(见图1):
图1 程序ClassABCTest.java运行结果
程序中我们声明了三个接口InterA、InterB、InterC和两个类 ClassABC、ClassABCTest。接口InterA和InterB是两个独立的接口,而接口InterC用关键字extends继承了接口InterA和InterB,事实显而易见,这是多重继承关系,即接口InterC同时继承了接口InterA和InterB。
综上,Java中类的继承是单重继承,但是却可以通过一个类实现多个接口这种方法来实现多重继承的功能,或者直接通过一个接口继承多个接口来实现多重继承的功能。接口不仅很好地解决了多重继承,对于单重继承层次较多、间接父类多的类结构,接口还可以避免子类成员的膨胀、庞杂、难以管理等问题,但接口仍然存在不一致性等问题。
即便是运用一个具有较全而完整的继承机制的语言,实际应遵循的原则也应该是尽可能保持继承层次体系的简单性,只有在条件非常充分的情况下才使用多重继承。
[1]许晓宁.JAVA技术实用教程[M].南京:东南大学出版社,2005.
[2]叶核亚.JAVA2程序设计实用教程(第2版)[M].北京:电子工业出版社,2007.
[3]布雷恩,等.JAVA2精要语言详解与编程指南[M].北京:清华大学出版社,2002.
[4]朱喜福.Java程序设计[M].北京:清华大学出版社,2004.
[5]王行言.JAVA语言与面向对象程序设计[M].北京:清华大学出版社,2000.
[6]刘艺.JAVA程序设计大学教程[M].北京:机械工业出版社,2006.
[7]Ian Joyner(著).对象揭秘:Java,Eiffel和c++[M].鲍志云(译).北京:人民邮电出版社,2003.