封裝

介紹封裝的概念。

物件導向最基本的原則,把真實世界的某個事物包成物件,裡面的資訊不對外公開,只公開某些特定方法讓別人使用,內部的實做及資料都隱藏起來,不讓人直接使用,也不需要讓別人直接使用。也就是所謂的 資訊隱藏(Information Hiding)

設想一個例子,

提款機,你不知道它裡面還有多少錢,也不知道內部的運做,不知道哪家公司生產的機器,但你還是會去使用他提供的方法:查詢餘額、提款。 因為他只開放這兩個方法給一般人使用,你要使用這兩個方法需要帶入的參數是提款卡及密碼,就可以完成你的需求。

class 提款機{
    private int 剩餘現金;
    private boolean 身分確認(提款卡、密碼){
        ...
    }
    private void 吐鈔(){
        ...
    }
    public void 提款(提款卡、密碼){
        if(身分確認(提款卡、密碼) == true)
            吐鈔();
    }
    public void 查詢餘額(提款卡、密碼){
        ...
    }
}

當然實際上更為複雜且嚴密(而且我對提款機不熟),但在怎麼複雜,使用上一般使用者只要知道使用哪些公開的方法就好(雖然不熟但我會領錢、查餘額),剩下的就是設計這個類別的設計師要負責的工作。

常用修飾子 private 、 public

private 私有

private是資訊隱藏會普遍使用的修飾子,開放全限最低,只有自己類別的成員能夠存取。

public 公開

與private相反,public是任何人都可以調用,通常用來表示這個方法可以供一般人呼叫,一個public的方法內可以呼叫多個private的方法來實作需要的功能。

其他修飾子請參考『存取修飾子』章節。

物件導向是將『資料及其方法』包裝成物件,而資料、方法的劃分都是設計師決定的,但要記得物件的核心是資料,而不是方法。 (data是主角)

封裝的概念是將資訊隱藏,只透過某些公開的方法讓外界存取使用。

Getter、Setter

為了資訊隱藏,我們常把重要資料設為private,要供別人(甚至自己)存取的時候,通常會利用getter()及setter()這種透過公開方法間接的存取。

來看個例子,學生的類別有姓名年齡3個欄位,提供兩個setter兩個getter:

class Student{
    private String firstName;
    private String lastName;
    private int age = -1;

    public void setName(String first,String last){
        if( first == null || last == null || first.length()==0 || last.length()==0 ){
            System.out.println("ERROR: name輸入錯誤,名字姓氏不得為空");
        }else{
            firstName = first;
            lastName = last;
        }
    }
    public void setAge(int a){
        if(a < 0){
            System.out.println("ERROR: age輸入錯誤,年齡不可能為負數");
        }else{
            age = a;
        }
    }
    public String getName(){
        if( firstName==null || lastName==null)
            return "unset";
        else
            return firstName + lastName;
    }
    public int getAge(){
        return age;
    }
}// end of class Student

這是常見的設計方法,資料成員的部份我都設為private,而公開了setName(.)及setAge(.)讓別人呼叫來設定name及age的值,這就是透過公開方法間接的設定隱藏的欄位,好處是我這樣寫可以在設定欄位前先做一些前處理(以上述程式來說就是檢查參數的合法性)。

在getter的部份,也公開了兩個方法可以讓別人存取到內部隱藏的成員,以getName()來說,可以在回傳出去前多做一步處理(這裡是把名跟姓串起來),這樣的設計方式是常見且容易維護的。

測試程式:

class Test {
    public static void main(String[] args) {

        Student s1 = new Student();
        s1.setName("小木","");
        s1.setAge(-500);
        System.out.println(s1.getName());
        System.out.println(s1.getAge());

        Student s2 = new Student();
        s2.setName("Tina", "Lee");
        s2.setAge(18);
        System.out.println(s2.getName());
        System.out.println(s2.getAge());

    }// end of main(String[])
}// end of class Test

執行結果:

ERROR: name輸入錯誤,名字姓氏不得為空
ERROR: age輸入錯誤,年齡不可能為負數
unset
-1
TinaLee
18

可以看到物件s1因為亂帶參數,所以用setter在設定前被先檢查出來,可以進一步增加程式的穩定性。

Last updated