封裝物件內部資料


封裝物件操作流程 的範例中,你在CashCard類別上定義了store()等方法,你「希望」使用者如下撰寫程式,這樣才可以執行stroe()等方法中的相關條件檢查流程:

CashCard card1 = new CashCard("A001", 500, 0);
card1.store(scanner.nextInt());

老實說,就目前的Java程式碼來說,你的希望完全就是一廂情願,因為CashCard使用者還是可以如下撰寫程式,跳過你的相關條件檢查:

CashCard card1 = new CashCard("A001", 500, 0);
card1.balance += scanner.nextInt();
card1.bonus += 100;

問題在哪?因為你沒有封裝CashCard中不想讓使用者直接存取的私有資料,使用者撰寫程式時,就有了自由存取類別私有資料的選擇,如果有些資料是類別所私有,在Java中可以使用private關鍵字定義:

package cc.openhome;
class CashCard {
    private String number;
    private int balance;
    private int bonus;
    ...略
    void store(int money) {
        if(money > 0) {
            this.balance += money;
            if(money >= 1000) {
                this.bonus++;
            }
        }
        else {
            System.out.println("儲值是負的?你是來亂的嗎?");
        }
    }

    int getBalance() {
        return balance;
    }

    int getBonus() {
        return bonus;
    }

    String getNumber() {
        return number;
    }
}

在這個例子,你不想讓使用者直接存取numberbalancebonus,所以使用private宣告,如此一來,編譯器會讓使用者在直接存取numberbalancebonus時編譯失敗,如果你沒有提供方法存取private成員,那使用者就不能存取,在CashCard的例子中,如果想修改balancebouns,就一定得透過store()charge()exchange()等方法,也就一定得經過你定義的流程。

如果沒辦法直接取得numberbalancebonus,那這段程式碼怎麼辦?

for(CashCard card : cards) {
    System.out.printf("(%s, %d, %d)%n",
                    card.number, card.balance, card.bonus); // 編譯錯誤
}

除非你願意提供取值方法(Getter),讓使用者可以取得numberbalancebonus的值,否則使用者一定無法取得,基於你的意願,CashCard類別上定義了getNumber()getBalance()getBonus()等取值方法,所以你可以如下修改程式:

for(CashCard card : cards) {
    System.out.printf("(%s, %d, %d)%n",
                    card.getNumber(), card.getBalance(), card.getBonus());
}

在Java命名規範中,取值方法的名稱形式是固定的,也就是以get開頭。

所以你封裝了什麼,封裝了類別私有資料,讓使用者無法直接存取,而必須透過你提供的操作方法,經過你定義的流程才有可能存取私有資料,事實上,使用者也無從得知你的類別中有哪些私有資料,使用者不會知道物件的內部細節。

在這邊對封裝作個小小結論,封裝目的主要就是隱藏物件細節,將物件當作黑箱進行操作。就如先前的範例,使用者會呼叫建構式,但不知道建構式的細節,使用者會呼叫方法,但不知道方法的流程,使用者也不會知道有哪些私有資料,要操作物件,一律得透過你提供的方法呼叫。

private也可以用在方法或建構式宣告上,私有方法或建構式通常是類別內部某個共用的演算流程,外界不用知道私有方法的存在。private也可以用在內部類別宣告,內部類別會在之後說明。

私有建構式的使用比較進階,有興趣可以參考 Singleton 模式