上一篇介紹了「修飾元」(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);
}
}
}
從以上的程式碼可以看到其他類別是可以透過Deposit和Withdraw這兩個方法去改變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());
}
}
這樣能改變和取得類別成員的值的方法分別稱為setter和getter。
你也可以定義某個類別成員只有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的強大吧~
留言列表