Java 學習記錄 34 — Encapsulation

張小雄
5 min readFeb 2, 2021

--

今天介紹 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?

Jean-Paul

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 訪問時就可以用到

--

--

張小雄
張小雄

Written by 張小雄

記錄成為軟體工程師的過程

No responses yet