ITEEDU

Java Gossip: 使用类别(Class)定义对象

对象导向设计中,对象并不是凭空产生的,您必须先定义您的对象,您要一个规格书,这个规格书称之为类别(Class)。

在Java中使用"class"关键词来书写类别(规格书),您使用类别来定义一个对象(object)时,您考虑这个对象可能拥有的「属性」(Property,在Java中则是用Field)与「方法」(Method)。属性是参与对象内部运算的数据成员,而方法则是对象与外界互动的动态操作。

您使用类别定义出对象的规格书,之后根据这个规格书来建构对象,然后透过对象所提供的操作接口来与程序互动。

举个例子来说,您可以定义一个对象:「球」。

考虑球有各种不同的颜色(或名称),以及球最基本的球半径信息,您想到这些信息应该可以取得,并可以进一步取得球的体积,当您在Java中要定义这些信息时,您可以如下进行定义:

Ball.java
public class Ball {
	private double radius; // 半径
	private String name;?// 名称
	// 无参数建构方法
	public Ball() {
		this(0.0, "no name");
	}
	// 有参数建构方法
	public Ball(double radius, String name) {?
		this.radius = radius;
		this.name = name;
	}
	public double getRadius() {
		return radius;
	}
	public String getName() {
		return name;
	}
	public void setRadius(double radius) {
		this.radius = radius;
	}
	public void setName(String name) {
		this.name = name;
	}
}?

一个定义良好的类别,即使在不看程序代码实作的情况下,也可以从定义中所提供的公开(public)方法看出这个类别的大致功能。

"class"是Java中用来定义类别的关键词,Ball是您所取的类别名称,记得一个类别的定义是这么作的:

public class Ball { 
	// 实作内容 
}

在类别中的运算参与数据(Field)及互动方法(Method),我们统称其为 类别成员(Class member)

上例中的radius、name成员是field成员,getRadius()与getName()是method成员。注意到"public"这个关键 字,它表示所定义的成员可以使用宣告的对象名称加上 '.' 运算子直接呼叫,也称之为「公用成员」或「公开成员」。而private这个关键词用来定义一个「私用成员」,它不可以透过参考名称直接呼叫,又称之为 「私有成员」。

在定义类别时,有一个基本原则是:信息的最小化公开。也就是说尽量透过方法来操作对象,而不是直接存取其内部运算参与数据(也就是field成员)。

信息的最小化公开原则是基于安全性的考虑,避免程序设计人员随意操作field成员而造成程序的错误,您可以在日后的程序设计中慢慢来体会;在稍后的实作中,您将可以看到,我们将不会radius与name两个私用成员直接进行存取,而是透过公开的方法来进行设定。

一个类别中的field成员,若宣告为"private",则其可视范围(Scope)为整个类别,由于外界无法直接存取私用成员,所以您使用两个公开方法 getRadius()与getName()分别传回其这两个成员的值。

与类别名称同名的方法称之为 建构方法 Cconstructor),也有人称之为「建构子」,它没有传回值。顾名思义,建构方法的作用是让您建构对象可以设定一些必要的建构信息,它可 以被重载(Overload),以满足对象生成时不同的设定条件。

您在实作中重载了建构方法,在不指定参数的情况下,会将radius设定为0.0,而name设定为 "no name",另一个建构方法则可以指定参数,this()方法用于对象内部,表示呼叫对象的建构方法,另一个就是this,它表示对象本身,您可以在 关于 this 进一步了解其作用。

定义好类别之后,您就可根据这个类别(规格)来建构对象,建构对象时使用new关键词,顾名思义,就是根据所指定的类别(规格书)「新建」一个对象:

Ball ball1 = new Ball(); 
Ball ball2 = new Ball(3.5, "red ball");

在上例中配置了ball1与ball2两个对象,ball1对象在建立时并不指定任何参数,所以根据之前对Ball类别的定义,ball1的radius 将设定为0.0,name设定为"no name";ball2则给定两个参数,所以ball2的radius设定为3.5,而ball2的name设定为"red ball"。

您可以透过公开成员来操作对象或取得对象信息,方法是使用对象名称加上「.」运算子,例如:

ball1.getRadius(0.1); 
ball1.setName("GBall");

以下先看个简单的程序:

SimpleClass.java
public class SimpleClass { 
public static void main(String[] args) { 
Ball b1 = new Ball(18.4, "red ball");
System.out.println("名称: " + b1.getName()); 
System.out.println("半径: " + b1.getRadius()); 
} 
} 

执行结果:

名称: red ball 
半径: 18.4

类别与对象这两个名词会经常混于书籍与文件之中,例如「您可以使用Scanner类别」、「您可以使用Scanner对象」,这两句在某些场合其语义是相 同的,不过要细究的话,两句的意思通常都是「您可以使用根据Scanner类别所建构出来的对象」,不过写这么长很烦,难免就省略了一些字眼。

Java会将参与内部运算的数据命名为field,其实是蛮有道理的,field在英文中有事件的参与者的意义,有限定范围的意思。基本上,在定义对象 时,field成员其作用范围要限定于对象之中,对对象内部数据的变更,都要透过公开方法来进行,避免field成员的作用范围离开了对象之外。