抽象化與封裝總是搞混嗎?這篇文章幫你一次整理清楚
學習物件導向(OOP)時,一定會遇到一個難關。
那就是抽象化與封裝。
這兩個概念很容易聽起來幾乎一樣。面試被問到「抽象化與封裝有什麼差別?」時,也很容易含糊帶過。
先從結論說起。
抽象化是決定「要顯示什麼」的設計觀點,而封裝是決定「要如何隱藏」的實作觀點。
掌握這一句話,就已經完成一半了。接著用範例把剩下的部分牢牢記住。
什麼是抽象化?
抽象化(Abstraction)是隱藏複雜的內部實作,只擷取並呈現必要的本質。
想想汽車。開車時,我們不需要知道引擎如何讓燃料爆炸。
方向盤、踏板、排檔。只要知道這個介面,就能開車。
也就是說,思考要向駕駛者公開什麼,就是抽象化。
用程式碼表示如下。
protocol Coffee {
func brew()
}
struct Americano: Coffee {
func brew() {
print("沖煮美式咖啡")
}
}
let menu: Coffee = Americano()
menu.brew()
// 輸出:沖煮美式咖啡
使用端只知道本質brew()。至於如何研磨咖啡豆、將水調到幾度,都不在關注範圍內。
這就是抽象化。
什麼是封裝?
封裝(Encapsulation)是將資料與處理資料的功能綁在一起,並阻止外部直接存取。
核心是隱藏與保護。
想想銀行帳戶。如果外部可以任意修改餘額,事情就嚴重了。
因此要隱藏餘額,只能透過存款、提款等既定管道進行變更。
class Account {
private var balance = 0
func deposit(_ amount: Int) {
guard amount > 0 else { return }
balance += amount
}
func getBalance() -> Int {
return balance
}
}
let acc = Account()
acc.deposit(1000)
print(acc.getBalance())
// 輸出: 1000
我們用private阻擋了balance。外部只能透過既定的入口deposit來變更值。
像這樣隱藏內部並控制存取,就是封裝。
所以兩者的關鍵差異是?
總結如下。
| 區分 | 抽象化 | 封裝 |
|---|---|---|
| 目的 | 隱藏複雜性,只公開本質 | 隱藏並保護資料 |
| 觀點 | 設計觀點(要什麼) | 實作觀點(如何做) |
| 問題 | 「要顯示什麼?」 | 「要如何隱藏?」 |
| 手段 | 介面、抽象類別 | 存取控制修飾詞(例如 private) |
來點出最容易混淆的地方。
因為兩者都會提到隱藏,所以容易搞混。
但隱藏的對象不同。
抽象化隱藏複雜的流程(邏輯),讓使用變得簡單;封裝則隱藏資料(狀態),加以安全保護。
什麼時候該在意哪一個?
實務上不是分開使用,而是一起使用,只是焦點不同。
- 設計新功能的介面時 → 專注於抽象化
- 需要維持類別內部狀態的完整性時 → 專注於封裝
- 協作時思考要對外公開的 API → 抽象化
- 安全管理值、避免錯誤時 → 封裝
面試會這樣問
Q. 請說明抽象化與封裝的差異。
關鍵在於觀點不同。抽象化是隱藏不必要細節、只呈現本質的設計概念;封裝則是隱藏資料、限制存取的實作概念。再補充抽象化透過介面、封裝透過存取控制修飾詞來實現,會更完整。
Q. 為什麼需要封裝?
如果外部直接修改物件狀態,資料完整性很容易遭到破壞。讓狀態只能透過既定方法變更,就能集中驗證邏輯,也更容易維護與除錯。
這兩個概念不是相反,而是一對搭檔。如果今天的範例讓你掌握了訣竅,下次寫程式時只要想一次:「我現在要顯示什麼,又要隱藏什麼?」OOP 就會清晰許多。

