品味Java(7):Java的面向对象编程技术
软件世界
学习进程:
品味Java之编程基础篇
……
4.流程控制
5.异常控制
6.面向对象编程
7.认识Java的包(Package)、标准包和Javadoc
……
从过程到对象的转变
学习面向对象的编程技术首先应该有一个编程思想的转变过程。C、Pascal程序员思考的是完成任务的过程,他们要写大量函数或过程来“堆起”一个应用程序。C语言采用面向过程的程序设计模型,但是由于C语言本身几乎没有支持代码重用的语言特性,并且缺乏统一的接口,使得当程序的规模达到一定程度时,程序员很难控制其复杂性。这对现在要求的快速开发来说是不可想象的。
面向对象编程技术可以使软件能够按一定规范由多人开发,将开发出来的各个部件再重新组装就构成了一个完整的系统。
认识面向对象编程
一个对象就是变量和相关的方法的集合,其中变量表明对象的状态,方法表明对象所具有的行为。一个对象的变量构成这个对象的核心,包在它外面的方法使这个对象和其他对象分离开来。例如:我们可以把汽车抽象为一个对象,用变量来表示它当前的状态,如速度、油量、型号、所处的位置等,它的行为则可以有加速、刹车、换挡等。我们操纵汽车时,不用去考虑汽车内部各个零件如何运作的细节,只需要根据汽车可能的行为使用相应的方法即可。
类(Class)
类是组成Java程序的基本要素。它封装了一类对象的变量和方法,是这一类对象的原型。定义一个类就是创建一个新的数据类型,实例化一个类就得到一个对象。在前几周的文章中,我们已经定义了一些简单的类,如HelloorldApp类。
public class HelloWorldApp{
public static void main(String args[]){
System.out.println("Hello World!");
}}
可以看出,一个类的实现包含两部分的内容,类声明和类体。格式如下:
类声明
{
类体
}
下面我们分别对每一部分加以详细讲述。
类的声明
类的声明完整格式如下:
[类访问权限] class 类名 [extends 基类名] [implement 接口名]
其中,“[ ]”的内容可以省略(可选项)。
类体的定义
类体中定义了该类所有成员变量和该类所支持的方法函数。通常变量在方法前定义,如下所示:
class className{
成员变量定义
方法定义
}
下例定义了一个Point类,并且声明了它的两个变量x、y坐标,实现init()对x、y赋初值。
class Ponit{
int x,y;
void init(int ix,int iy){//类的方法,初始化成员变量
x=ix;
y=iy;
}}
类中所定义的变量和方法都是类的成员。对类的成员可以设定访问权限,来限定其他对象对它的访问,访问权限有以下几种:private、protected、public、friendly。同时,对类的成员来说,又可以分为实例成员和类成员两种。
成员变量
类的成员变量的声明和一般变量的声明很类似,只是在类体中声明罢了。其完整格式如下:
[修饰符]类型 变量 [=初始值][变量];
其中[ ]内的内容为可选项。
最简单的成员变量(也称为类的属性)的声明为:
Type Name;
如声明为:int x,y; //多个变量用逗号隔开
类的成员变量的类型可以是Java中的任意数据类型,包括简单类、数组、类和接口。在一个类中,成员变量应该是惟一的,但是成员变量的名字可以和类中某个方法的名字相同,例如:
class Point{
int x,y;
int x(){
return x;
}}
其中,方法x()和变量x具有相同的名字。
类的成员变量和在方法中所声明的局部变量是不同的,成员变量的作用域是整个类,而局部变量的作用域只是方法内部。对一个成员变量,我们还可以限定它的访问权限,用static限定它为类变量,或者用以下的修饰符限定:
Final:用来声明一个常量,如:
class FinalVar{
final int CONSTANT=50;
……
}
示例中声明了常量CONSTANT,并赋值为50。对于用Final限定的常量,在程序中不能改变它的值。通常常量名用大写字母。
类的应用实例
为了说明Java中类的使用,我们用两个小程序来说明问题。
声明一个类:
// ClassOne.java
public class ClassOne{
int i;//成员变量
public ClassOne(int var){
i=var;//给成员变量赋初值
}
public void add(int j){
i=i+j;//add中将两整数求和
}}
在这个类中,我们定义了一个成员变量i;一个ClassOne()构造方法(构造函数),这个方法的名称和类的名称同名,用来初始化对象。还定义了一个add()方法,它实现了整数的求和运算。
现在我们如何使用上面的类呢?
//ClassOneTest.java
public class ClassOneTest{
public static void main(String[] args) {
ClassOne c=new ClassOne(8);
c.add(100);
System.out.println(c.i);
}}
如上例所示,我们在创建类的实例时,会使用ClassOne c=new ClassOne(8)语句,该程序会默认地自动调用ClassOne的构造函数。这个构造函数给ClassOne类的成员变量赋值,然后调用add()方法,最后输出成员变量的值。
继承(Inheritance)
通过对象、类,我们实现了封装,通过子类我们可以实现继承。对于上例来说,公共汽车、出租车、货车等都是汽车,但它们是不同的汽车,除了具有汽车的共性外,它们还具有自己的特点(如不同的操作方法、不同的用途等)。这时我们可以把它们作为汽车的子类来实现,它们继承父类(汽车)的所有状况和行为,同时增加自己的状态和行为。通过父类和子类,我们能够实现类的层次,可以从最一般的类开始,逐步特殊化,到定义一系列的子类。
多态(Polymorphism)
类的多态是指一个方法具有多种功能,或者相同的接口有多种实现方法。Java编程通过方法重载(Overloading)、覆盖(Overriding)和接口(Interface)来实现多态性。
方法重载是指多个方法具有相同的名称,只是方法的参数个数和类型不相同。根据不同的参数个数和类型来选择使用不同的方法。比如一个画图的类,它有一个Draw()方法,我们可以给它传递不同的参数,如果传递的是一个字符串,就输出字符串;如果是一个矩形(可有是两个点的坐标值),就画矩形;如果是圆形,则画圆……总之是根据参数的不同来确定调用的什么方法。
覆盖是指类派生过程中,子类与父类的方法不仅名称相同,参数也完全相同。这时子类中的方法覆盖了父类的方法,具有自己的特征。
接口实际上是一种特殊的类,接口中只有方法的原型和常量,而不实现具体的操作行为。
接口在语法上与类非常相似,但是没有实例变量和实现的方法。这也就是说,我们在定义接口时,不必关心实现方法的细节。比如,我们可以在接口中放置一些共同行为,而把特殊的行为放到具体的类中,把具体的实现方法单独出来。接口的方法在接口里定义为public或abstract。接口里的成员变量可以是public、static和final。接口和抽象类的主要区别是一个接口提供了封装成员函数的方法而不必强迫用户继承类。
接口的应用实例
定义接口:
// FileName:interfaceTest.java
public interface interfaceTest{//接口包含一个方法(成员函数)
int i=100;
void Print();
}
提示:接口和类很相似,但接口中没有变量,只有常量。
实现接口
使用接口时,用implements关键词来表达一个类使用了某一个接口。类中可以不使用接口中定义的常量,但必须实现接口中定义的所有方法。一个类也可以实现多个接口,在implements子句中用逗号分隔开。
上例(interfaceTest)接口的实现例程:
//FileName:MyClass.java
class MyClass implements interfaceTe
st{//实现一个接口
public void Print(){System.out.println(i);}//接口定义的方法,i为接口中定义的常量
int num=11;//MyClass类的成员变量
public void Add(){//Add为MyClass类的方法,而不是接口中定义的方法
num+=i; //求MyClass类中的成员变量值与接口中常量值之和
System.out.println(num);
}}
总的来说,学习Java的面向对象编程技术决不是一件容易的事。在本文中,笔者不是教你完全理解和掌握这种技术(这里的少量示例和练习是完全不够的),而是通过一些例子和概念让初学者能从中领悟Java面向对象编程的一定思想。如果你想深入Java的面向对象编程技术,则可以参考《Java面向对象编程指南》一书。