From Gossip@caterpillar

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();
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成員的作用範圍離開了物件之外。