iT邦幫忙

2026 iThome 鐵人賽

DAY 20
1

今天不寫 Code,前 19 篇一股腦去改程式,寫測試。發現好像有一些基本觀念沒有介紹,就被跳過了。趁這段時間來補上資訊,否則又怕直接水到 Day 30,又留下懸念。

封裝(Encapsulation)

valvarclass 等,可以加上一些魔法語句來防止閒雜人等存取。前幾天有看到:

var name: String
	private set

這個 private 就是術語之一,代表只有這個 class 裡頭 的人,才能存取。
在 Kotlin 之中,預設情形如果不寫,就是 public 的,也就會變成公共財,大家都能用。

還有一個比較特別的是 protected,讓自己的子孫可以存取。從 Code 來看:

open class Car {
	protected val brand = "toyota"
	private val engine = 1800
}

如果任何人繼承了 Car,則可以存取 brand

class Rav4 : Car() {
	fun main() {
		println(brand)  // 👈🏼 可以取得 "toyota"
		println(engine)  // 🚷 錯誤,因為 engine 是 private
	}
}

這時如果 Rav4 在其他地方被 new 出來,也無法存取 brand。

fun main() {
	val car = Rav4()
	car.brand // 🚷 無法,因為不是子孫,無法取得
}

資料型態補充

變數的型態,前幾章已經有介紹過呈現真/假使用的—— Boolean,以及整數的大家庭,最常用的:IntLong,以及比較少用到的 ShortByte。當然不要忘記表達文字的—— String 和一個字的 Char

在數值方面,還有一個家族,就是浮點數(基本上就是有「小數點」的數字),能拿來做更精細的運算。Kotlin 中,浮點數主要有兩個 Type:FloatDouble
來看看兩者有什麼異同:

資料型態 (Type) 記憶體大小 (Size) 浮點數精度 (Precision) 適用情境舉例
Float (單精度) 4 Bytes (32 bits) 6 - 7 位有效數字 圖形處理 (3D 運算)、 行動裝置遊戲開發 (省記憶體)
Double (雙精度) 8 Bytes (64 bits) 15 - 17 位有效數字 科學計算、數學公式分析、 大多數程式的預設小數型態

Kotlin 很聰明,如果啥都不寫:

val point = 1.5

預設會給 Double,只有加上 f 才會預設是 Float。(e.g. 1.5f)
如果小數點真的太多啦,直接用 Double 就好,以免資訊遺失。

Interface 的黑暗孿生兄弟

即是 abstract class (中譯應該是:抽象類別),interface 裡頭需要先定義合約裡頭,實作的人需要實作的內容。而 abstract class 則除了合約內容,已經有一些做好的 Function,不用重新實作可以直接用。 abstract class 比較像買房後建商附的裝潢,買房後不用重新裝潢,可以直接使用,但房型已經定義好的房間種類,則需要遵守(不可能廚房變房間吧 🫨)。
Interface 則是照著設計圖去做房間的裝潢即可。

直接來看 Code:

interface MyComputer {
	fun boot(): Boolean
	fun shutdown(): Boolean
}

任何實作這個 MyComputer interface 的,都需要服從契約—— 實作這兩個 Function。

class EeeePC(private val machine: Machine) : MyComputer {
	// 👇🏼 要實作
	override fun boot(): Boolean {
		return machine.boot();
	}
	
	// 👇🏼 要實作
	override fun shutdown(): Boolean {
		return machine.shutdown()
	}
}

不過,如果 MyComputer 都有共同的工作要做,就直接用 abstract class 將重複的行為做定義就好:

// 👇🏼 abstract class 可以 inject
abstract class MyComputer(private val lManager: LanguageManager) {
	
	// 可以留契約
	abstract fun boot(): Boolean
	abstract fun shutdown(): Boolean
	
	// 可以先建立好行為
	fun startTwEnv() {
		lManager.switchToZhTw()
		boot() // 👈🏼 很厲害的方式是,可以直接去叫契約,行為就看實作方怎麼做
	}
}

只要繼承自 MyComputer,就需要實作契約,不過也免費的得到了預先定義好的 Function。

class EeeePC(
	lManager: LanguageManager,
	private val machine: Machine
) : MyComputer(lManager) {
	// 👇🏼 要實作
	override fun boot(): Boolean {
		return machine.boot();
	}
	
	// 👇🏼 要實作
	override fun shutdown(): Boolean {
		return machine.shutdown()
	}
}

如此一來這個 EeeePC 只要被 new 出來後,就可以使用 startTwEnv() 了!

TL;DR

  • 封裝(Encapsulation):用可見性修飾詞把類別的成員擋起來,防止閒雜人等隨便存取,保護內部資料。
  • private:只有這個 class 裡頭的成員才能存取;var name: String private set 就是最典型的用法——外面能讀不能改。
  • public:Kotlin 的預設可見性,不寫就等於公共財,誰都能用。
  • protected:開放給自己和繼承的子孫使用;像 Car 裡的 brandRav4 繼承後拿得到,外部 new 出來的物件卻摸不到。
  • 繼承 class 要加括號class Rav4 : Car() 的括號代表呼叫父類別建構子;interface 才不用加,兩者別搞混。
  • Float:4 Bytes 的單精度浮點數,約 6-7 位有效數字,適合圖形運算、遊戲這種省記憶體的場景。
  • Double:8 Bytes 的雙精度浮點數,約 15-17 位有效數字,也是 Kotlin 小數字面值的預設型態,怕精度遺失就用它。
  • abstract class:interface 的孿生兄弟,除了抽象方法當合約,還能先寫好共用的 Function(例如 startTwEnv()),繼承者免費獲得現成行為。
  • 抽象方法可以在類別內先被呼叫startTwEnv() 裡直接叫 boot(),行為由實作方決定——這是抽象類別「定義流程、延遲細節」的厲害之處。

上一篇
[Day19] 做太多不好,負責一件事就好
下一篇
[Day21] 改變心情
系列文
我的第一個手作りAndroid App!快樂學習物件導向程式設計!22
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

2 則留言

0
chiaominchang222
iT邦新手 4 級 ‧ 2026-09-08 20:27:35

不行了不行了 撐不住了 老師好強

0
AndyAWD
iT邦新手 1 級 ‧ 2026-09-08 23:43:32

abstract 好用 !

我要留言

立即登入留言