close

上一篇介紹了「修飾元」(Modifier),本篇就延伸內容,介紹物件導向語言中其中一個特色「封裝」(Encapsulation)

封裝的作用就是對類別成員的一種存取保護,可以先看以下的例子:

public class Account {
    
private int balance;
    
    public Account()
    {
        System.out.println("Created new account.");
    }
}

public class ATM {
    public static void main(String[] args) {
        Account account = new Account();
       
account.balance = 1000; // 會報錯
    }
}

當ATM的main方法執行 account.balance = 1000 時,由於balance在Account類別中的修飾元是private,除了Account以外的類別都無法存取,所以編譯器會報錯。

如果改成
public int balance;
任何類別都能任意修改balance的值,例如
account.balance = -1000;
但是常理來說,銀行帳戶的餘額不能為負值。

這時你可能會想,只要其他類別改變balance的值之前先做檢查不就好了嗎?
但是!如果你是負責開發Account這類別的人,你要明白不可能所有的人都知道類別成員的限制,就像Account.balance不能為負值。
所以這時候就要使用「封裝」去限制類別成員的存取,以致於其他人使用你開發的類別不會出錯。

修改Account類別的程式碼

public class Account {
    
private int balance;
    
    public Account()
    {
        System.out.println("Created new account.");
    }
    
    
public void Deposit(int money)
    {
        if (money < 0)
            System.out.println("Cannot deposit negative amount");
        else
        {
            
balance += money;
            System.out.println("Deposited: $" + money);
            System.out.println("Balance: $" + balance);
        }
    }
    
    
public void Withdraw(int money)
    {
        if (money < 0)
            System.out.println("Cannot withdraw negative amount");
        else if (balance - money < 0)
            System.out.println("Cannot withdraw money because the balance not enough");
        else
        {
            
balance -= money;
            System.out.println("Withdrew: $" + money);
            System.out.println("Balance: $" + balance);
        }
    }
}

從以上的程式碼可以看到其他類別是可以透過DepositWithdraw這兩個方法去改變balance的值,而且還提供了檢查機制,使balance的值是在合理範圍裡。

所以ATM這個類別可以順利執行又不會任意修改到balance的值了。

public class ATM {
    public static void main(String[] args) {
        Account account = new Account();
        account.Deposit(-100);       
// 印出Cannot deposit negative amount
        account.Deposit(1200);      // 印出Deposited: $1200. Balance: $1200
        account.Withdraw(-100);    // 印出Cannot withdraw negative amount
        account.Withdraw(1500);   // 印出Cannot withdraw money because the balance not enough
        account.Withdraw(1000);   // 印出Withdrew: $1000. Balance: $200
    }
}

 

在java的編程世界中,有一套不成文的習慣。
如果是供其他類別修改自己類別成員的值的方法,就以set+變數名稱為個方法的名稱,如以下的setName
如果是讓其他類別取得自己類別成員的值的方法,就以get+變數名稱為個方法的名稱,如以下的getName


public class Account {
    
private String name;
    
    public Account()
    {
        System.out.println("Created new account.");
    }
    
    public void
setName(String name)
    {
        this.name = name;
    }
    
    public String
getName()
    {
        return name;
    }
}

public class ATM {
    public static void main(String[] args) {
        Account account = new Account();
        account.
setName("ChrisCSIE");
        System.out.println("Account name: " + account.
getName());
    }
}

這樣能改變和取得類別成員的值的方法分別稱為settergetter
你也可以定義某個類別成員只有setter或只有getter,去限制它只能被其他類別修改或只能讀取。

除了類別成員外,類別裡的方法你也可以用「修飾元」去定義哪些方法是可以被其他類別使用,哪些只能在自己類別使用。
例如將原本在 Deposit 和 Withdraw 裡的判斷條件 if (money < 0) 放到 CheckMoney 這個方法,由於這只是類別內部的運算,不需要讓其他類別知道運算的過程,所以是可以把private作為它的修飾元

    public void Deposit(int money)
    {
        if (
CheckMoney(money))
            System.out.println("Cannot deposit negative amount");
        else
        {
            balance += money;

            System.out.println("Deposited: $" + money);
            System.out.println("Balance: $" + balance);
        }
    }
    
    public void Withdraw(int money)
    {
        if (
CheckMoney(money))
            System.out.println("Cannot withdraw negative amount");
        else if (balance - money < 0)
            System.out.println("Cannot withdraw money because the balance not enough");
        else
        {
            balance -= money;

            System.out.println("Withdrew: $" + money);
            System.out.println("Balance: $" + balance);
        }
    }

    private boolean CheckMoney(int money)
    {
        
if (money < 0)
            return false;
        return true;
    }

以上就是本篇簡單介紹「封裝」的概念,希望能幫助大家更加深入了解OOP的強大吧~

arrow
arrow
    全站熱搜
    創作者介紹
    創作者 Chris_U in CSIE 的頭像
    Chris_U in CSIE

    Chris_U的CSIE部落格

    Chris_U in CSIE 發表在 痞客邦 留言(0) 人氣()