今天介紹 Encapsulation(封裝)
你有沒有想過為什麼 Class field 我們通常用 private 配合 getter、setter 而不直接用 public 呢?
我在還不清楚 Encapsulation 的好處時,甚至覺得是脫褲子放屁,麻煩的要死
public class Player { public String name;
public int health;
public String weapon; public void loseHealth(int damage) {
System.out.println("Lose hp: " + damage);
this.health -= damage;
if (health <= 0) {
System.out.println("GG!");
}
}
}
一個簡單的Player Class,filed 都直接設 public,也沒有弄 constructor
public static void main(String[] args) {
Player player = new Player();
player.name = "Bob";
player.health = 100;
player.weapon = "MP7A1";
player.loseHealth(50);
System.out.println(player.health);
player.loseHealth(60);
System.out.println(player.health);
player.health = 500;
System.out.println(player.health);
}
輸出結果:
Lose hp: 50
50
Lose hp: 60
GG!
-10
500
可以看到調用者能在其他地方隨便修改數值
明明 hp-10 遊戲結束了 還能補充 HP 超過滿值 100 而變成 500
且隨著業務拓展 代碼要修改 變複雜之時
public String weapon;
改成
public String Bigweapon;
那之前調用過 weapon 的地方一併全部都要改名成 Bigweapon
外部某個地方的 player.weapon
若沒改到就會出問題
在我們練習時的項目都很小,改起來很方便很快
但實際業務時,代碼數量很龐大且連代碼可能也不是我們寫的
很難確定哪邊漏掉了沒改到,這樣的話未來勢必會出現 Bug
那調用的功能可能也不是每天日常業務會用到的
就像網站上那麼多按鈕跟功能
有的怕是半年一年都沒人使用
但可以預期的就是哪天一定會出問題
所以解決問題的方法就是 Encapsulation
public class Player { public String name;
public int hp = 100;
public String weapon; public Player(String name, int hp, String weapon) {
this.name = name;
if (hp > 0 && hp <= 100) {
this.hp = hp;
}
this.weapon = weapon;
} public void loseHealth(int damage) {
System.out.println("Lose hp: " + damage);
this.hp -= damage;
if (hp <= 0) {
this.hp = 0;
System.out.println("GG!");
}
} public int hpCheck() {
System.out.println("HP: " + this.hp);
return this.hp;
}
}
使用了 constructor 並在初始化時添加 if 限制
也在 loseHealth(int damage)
中改成血量低於0時就變0
甚至名子 health 改成 hp
public static void main(String[] args) {
Player player = new Player("Bob", 500, "MP7A1");
player.hpCheck();
player.loseHealth(50);
player.hpCheck();
player.loseHealth(60);
player.hpCheck();
}
輸出結果:
HP: 100
Lose hp: 50
HP: 50
Lose hp: 60
GG!
HP: 0
就算調用時初始化填 500,還是會變成 100
且外部現在是調用 hpCheck() 也不需要一起改名子
只要在內部確定好 hpCheck() 返回的數據是一樣的
改名也只需要在內部統一修改 快捷鍵 shift + f6 整頁一起修改
不管內部名子或功能怎改 外部都不用擔心
這就是 Encapsulation(封裝)的好處
這樣外部不用管內部到底長啥樣
只要調用時給我需要的數據即可
如同手機或網站或很多工具一樣
使用者不用了解究竟內部如何實現
只要使用者要使用功能時 能正常運作即可
同學問說:啥時要設 getter 或 setter?
If the field will only be used inside the class, then there’s no need to create a getter. You’ll see examples of that during the course.
So if you need external classes to access your fields, then provide a getter, otherwise don’t
簡單概括,要從其他 class 訪問時就可以用到