owned this note changed 8 months ago
Linked with GitHub

第五屆 Kotlin Book Club for 深入淺出 Kotlin

Contact & Host: Gobby f8502106@gmail.com
書單 「深入淺出 Kotlin 」天瓏書局的連結
讀書會場次:(注意‼️每週舉行至 12 月) 報名參加讀書會


第一章 千里之行始於足下:試試水溫

  • Location: Zoom
  • Date: 2023-08-15 21:00 PM
  • 導讀人: 范聖佑
  • 簡報連結
  • 影片連結
  • Host: Gobby
  • Participants:
    • Gobby
  • 我有問題想問🙋

第一章課程筆記🖊️


第二章 成為變數:所有的程式碼都需要一種東西-變數

第二章課程筆記

筆記內容

Primitive type v.s. Object type
val和var的差別我是記最後一個字,l只有一條所以不能改、r有分岔有兩條路感覺就是可以改XD
Var = variable

Jim (2023年8月22日,下午9:25)
Val = value
val 就是不可變了
VAR 是可變的
剛剛提到用數字當變數命名可以這樣
val 1 :Int=1
但不建議

但在 java 裡面的 final class 又是另一個概念了 XD
val 是唯讀變數,const val 是編譯時期常數
https://dev.to/mujeebkhanj2326/what-is-the-difference-between-val-and-const-val-in-kotlin-2b6n
naming rule
https://kotlinlang.org/docs/coding-conventions.html#function-names

QA
Kotlin 是儲存物件的參考,所以在執行上會用掉比 Java 多的記憶體嗎?(因為杯子和值都會佔用記憶體?)

var 和 val 一個值可變一個不可變,有比較好記的方式嗎(還是用太少了?還沒很直覺記憶)
val -> value, var-> variable

變數是不是也不能用數字開頭? (對 名稱) (edited)
val 1 :Int=1
但不建議

var x = 5 var y = x y = 6 println(x) println(y) 這樣 ref 的概念 x print 出來應該是 6 ?
fun main() {
var x = 5
var y = x
y = 6
println(x) // 5
println(y) // 6
}
如果是基本資料型態( boolean, char, byte, short, int, long, float, double,)的話她會複製一份值所以x不會被影響,如果是其他類別或是list就會是傳址所以x會不一樣 參考網址


第三章 離開main函式:該提升檔次,學學函式了

第三章課程筆記

筆記內容

Q: 請問:print©和print(“\(c”)有何不同? A: 用\)符號的話要加在""裡,表示他也是字串的其中一部份,可以同時結合其他字串使用,比較方便

Q 想知道readln和readLine的差別,在這個程式會有影響嗎?
https://hyperskill.org/learn/step/11224


第四章 淺嚐類別:是時候看些Kotlin 基本型態以外的東西了

第四章課程筆記

筆記內容

破冰 https://miro.com/app/board/uXjVMp7fk_0=/?share_link_id=563011672523

類別 Class- 基本資料型態(ex: Int, Long) / 特殊資料型態(ex: 定義一個類別狗狗Dog)
屬性 - 有什麼特徵(ex: 重量, 名字,品種)
涵式 fun -能做的行為(ex: 會叫)
物件Object - 一種類別的實體


第五章 子類別與超類別:善用繼承

  • Location: Zoom
  • Date: 2023-09-12 21:00 PM
  • 導讀人: Iris
  • 簡報連結
  • 影片連結-未完成
  • Host: Gobby
  • Tech Support : Johnny Sung、梓育
  • Participants:
    • Gobby
    • David(梓育)
    • Johnny Sung
    • YH Lai
    • 黑貓(五更琉璃)
  • 我有問題想問🙋

問題記錄
  1. 問題1. Open是否跟public一样?

    (補充回答:
    在Kotlin中,open和public是兩個不同的關鍵字,具有不同的含義和用途。
    public:public是一個可見性修飾符,用於指定類、函數、屬性或其他成員的可見性。當你將類、函數或屬性標記為public時,它可以從任何地方都被訪問,沒有訪問限制。
    open:open是一個修飾符,用於標記類、方法或屬性,表示它們是可以被繼承或覆蓋的。在Kotlin中,默認情況下,類和類的成員都是不可繼承或覆蓋的,如果你想允許其他類繼承或覆蓋它們,你需要將它們標記為open。這個關鍵字主要用於創建可繼承的類層次結構,允許其他類繼承它們並提供自己的實現。
    )

  2. 問題2 我可以多重繼承嗎?例如汽車是車子又是交通工具類似這樣
    留言區回應 好像不行,記得 C 可以多重繼承,JAVA/Kotlin 要用 interface
    (補充回答: 不能,Kotlin只能單向繼承,其餘只能用inter face如下,我嘗試簡單寫一個範例,請大家鞭小力一點, 在例子中,我們定義了兩個接口:Vehicle和Car,然後創建了一個類CarImpl,該類實現了這兩個接口。通過這種方式,CarImpl類獲得了Vehicle和Car兩個接口的功能,實現了類似多重繼承的效果。)

interface Vehicle {
    fun start()
    fun stop()
}

interface Car {
    fun drive()
}

class CarImpl : Vehicle, Car {
    override fun start() {
        println("Car started")
    }

    override fun stop() {
        println("Car stopped")
    }

    override fun drive() {
        println("Car is driving")
    }
}

fun main() {
    val car = CarImpl()
    car.start()
    car.drive()
    car.stop()
}

  1. 所以繼承只能繼承一個類別,多的類別要使用實作?

對,沒錯

  1. 那我狼繼承犬然後犬繼承動物這樣包咧?
    Wolf-> Canine -> Animal就是今天的範例

  2. extend 跟 implement 有什麼主要差異?
    前者是繼承class用的,後者是實做interface用的

  3. 請問,文件檔名可以不跟class類名不同嗎?
    可以唷

第五章課程筆記

筆記內容

Subclasses and Super classes: Using Your Inheritance (子類別和超類別)

今天的主要主題會延續上次的內容來講講「繼承」

Agenda

  • 什麼是繼承
  • 設計一個Animal class階層結構圖
  • 使用IS-A測試階層
  • 使用Kotlin依照類別圖撰寫Animal superclass
  • 使用Kotlin撰寫繼承自Animal class的subclass
  • 使用繼承類別(應用場景)

什麼是繼承


如圖中所是,子女除了自己買的三樓以外,也擁有父母買的頂樓唷XD

那繼承有什麼特點呢?

  1. 父母擁有的我都有
  2. 父母能做的我都能做
  3. 不用努力了
  4. 但還是可以擁有自己的東西
    以上是生活中對於繼承的定義
  • 那在程式上的繼承(inheritance)是物件導向中的一個重要概念
  • Suberclass
  • Subclass
  • Definition: A superclass contains common properties
    and functions that are inherited by one or more subclasses.
    A subclass can include extra properties and functions, and can override the things that it inherits.
  • 以下圖片代表Car有兩個屬性以及三個方法,而ConvertibleCar也是有三個方法

註1:繼承箭頭的方向是有意義的,兒子都指向父親

註2:UML 分三個區域

  • class 的名字
  • 裡面有的屬性 (properties)
  • 裡面有的方法 (method)
繼承的特點
  • Superclass屬性和方法都會被繼承
  • 可重複使用 Superclass 可被多個Subclass 繼承

設計一個Animal class階層結構圖

接著我們就要來依照剛剛的概念來建立階層結構圖,我們先去用下圖來觀察

  • Design Animal class

  • Using inheritance to avoid duplicate code in sub class

    接著我們就把那六隻動物畫成結構圖看看,把他們共通的屬性提取出來

  • What should the subclasses override?
    實作Subclass 特有的屬性和方法

使用IS-A測試階層

左圖是測試成功的範例,因為河馬是個動物,所以河馬這個類別繼承了動物這個類別的屬性與方法
注意:這邊的繼承只能是單向的
右圖則是失敗的範例,這兩個類別關係並無繼承關係

接著我們用程式碼來看看吧,我們用" is "來定義

使用Kotlin依照類別圖撰寫Animal superclass

那接著我們要按照剛剛的圖來實作囉,請大家打開IDE

起始的頁面應該如下

接著就來定義一個新的Animal class


那我們剛剛只是定義了一個一般的class,那我們要怎麼樣才能告訴程式說我們要他是一個super class呢?

簡單來說就是記得增加"open"(如上圖)

修改完如下

使用Kotlin撰寫繼承自Animal class的subclass

寫完super class那接著就來寫sub class
那怎麼寫呢?

這樣就是一個完成sub class的起手式了

  • 如果superclass建構子有定義參數,我們也要在subclass建構子傳入相呼應的參數。

那接著我們就需要來把子類別的正確屬性和方法 override下來
先從屬性的修改開始

這邊要分為兩個情景: val和var

前者要記得都要增加override。

接著來對方法(method)來override,就是在我們的fun前面也增加 來override

完成之後,您會看到IDE大概長這樣

(補充:可以使用快捷鍵自動Override,Ctrl+O,或者ALT+INSERT->Overide Methods)

記得參數與型別需要一致,也就是超類別如果有參數的話,子類別也需要補上,如下圖所示

那Animal 的 project最後我們就按照課本,增加兩個子類別Wolf(狼)和Canine(犬科動物),參考下圖

  1. 新增Open Class

  2. Override方法 roam

  3. 增加Wolf的class

使用繼承類別


執行結果

  • Using a super type for a function's parameters and return type

    執行結果

    所以我們就可以發現我們也可以把class當成參數傳進來。

第六章 抽象類別與介面:認真的多型

第六章課程筆記

筆記內容

今天的主題是抽象類別與介面,進行的方式會依照課本的編排來介紹這兩個東西。

大綱

  1. Abstract Class- 抽象類別
  2. Interface- 介面
  3. 抽象類別與介面的不同
  4. 什麼是多型?
  5. 物件的類別檢查與轉型
  6. 追加內容

回顧上禮拜Animal的類別階層

我們知道了如果有父類別,我們的子類別就能繼承它的方法和屬性
但如果有個類別你不希望實例化

抽象類別是半成品,不能被直接實例化

  • 把指定屬性與方法留給子類別實作
  • 子類必須「處理」抽象的屬性與方法

    白色框框是整個類別
    如果是程式上的實作的話如下



    可以利用IDE來快速建立我們需要的程式

    最後完成結果如下

    所以我們目前有以下的繼承關係圖

Interface- 介面

類別之間定義相同的行為還有其他方式

  • 介面可以為不同的類別提供一樣的「行為」
  • 可提供「具體」的行為實作
  • 一個類別可以實作多個介面
  • 可以使用匿名(Anonymous)類別獨立實作

    那回到程式碼
    原本的長這樣

    接著我們要建立新的介面如下

    記得TODO要處理掉,不然會出錯喔

    所以我們現在程式新的關係圖如下

抽象類別與介面的不同

什麼是多型?




執行看一下結果吧

虛線是實作,實線是繼承

換另一個例子

所以我們會有很多不同職業的顧客




但如果我們要他付錢的話會重複很多次

所以我們應該要使用interface


如法炮製於其他職業

接著修改Store()


執行結果

物件的類別檢查與轉型

Kotlin提供不少方法來檢查物件的類別及變換

  • is
  • as
  • when

追加關鍵字

設計模式(Design Patterns)


第七章 資料類別:處理資料

  • Location: Zoom
  • Date: 2023-09-26 21:00 PM
  • 導讀人: Recca
  • 簡報連結
  • 影片連結-未完成
  • Host: Gobby
  • Tech Support : Johnny Sung、梓育
  • Participants:
    • Gobby
    • 梓育(ziyu)
    • YH Lai
  • 我有問題想問🙋

  1. 那多餘3的話,應該要怎麼做呢? : 如果多於3的話,那就不會用這種key value pair的方式,而是用2維陣列去處理

第七章課程筆記

筆記內容

今日主題 : 處理資料 - 沒有人想要浪費生命重新發明輪子
Data Class

Agenda

  • equals
  • Any類別
  • 實作equals要注意的事
  • data class
  • 實戰
    • Pair
    • Triple

Equals

比較對象是否相等,寫法上可能會看到如下

但這邊的Any是什麼呢? Any類別(對應到Java的Object)

Any 類別

所有的class的都繼承自Any,所以所有判斷都要和Any底下的類別去做比較
只有Any才能接受所有類別

實作equals要注意的事

  • 自反性 (Reflexive):
    對任意非空值x,x.equals(x) 應為 true
  • 對稱性 (Symmetric):
    對任意非空值x、y,x.equals(y)應等於y.eqauals(y)
  • 遞移性 (Transitive)
  • 一致性(Consistent):
    對任意非空值x、y,只要不更動這裡面的值,無論呼叫幾次,x.equals(y)回傳要一樣
  • x.equals(null)要等於false
    但JS內建的equals是少數程式語言不符合以上五點的e.g NaN

DataClass

data class 幫我們實作了

  • equals()
  • hashCode ()
  • toString()
  • componentN()
  • copy()
    在kotlin的定義
fun main() { val oreo = Cat("Oreo") oreo.age = 5 println(john.toString()) // Cat(name=Oreo, age=5) // Kotlin幫你完成的 val (name, age) = oreo // componentN 可以快速依照你原本設定的attribute來建立東西 val biscuit = oreo.copy(name = "Biscuit") // copy是希望我們有類似但稍有差別的東西用的 }

可以發現我們就不需要寫getter 和 setter了~

如果我們今天有些參數不希望它進到編譯器被處理,那我們也可以這樣寫

實戰



如果多於3的話,那就不會用這種key value pair的方式,而是用2維陣列去處理


https://ithelp.ithome.com.tw/2023ironman/kotlin#ir-list

第八章 null 與例外:安然無恙

  • Location: Zoom
  • Date: 2023-09-26 21:00 PM
  • 導讀人: Dion
  • 簡報連結
  • 影片連結-未完成
  • Host: Gobby
  • Tech Support : Johnny Sung、梓育
  • Participants:
    • Gobby
    • Mamu
    • YH Lai
  • 我有問題想問🙋

問題紀錄
  1. null 的變數會佔用記憶體嗎?

  2. 用!!這樣是否就不用在寫 null 相關的防呆?

  3. 這些null的判斷似乎有可能用在資料庫讀出資料時使用

  4. try catch 有回傳值?那任何值都可以?怎麼定義回傳的是 String or int or 類別 class 等等?如果回傳的是 List<WOW> 類似這樣的?

  5. 如果在finally也能放回傳值嗎?可以

  6. 如果try catch內return是會中斷try catch嗎? 會

  7. Kotlin裡是有runtime exception 的概念嗎?有,即執行階段會跑出來 exception ,可先確認一下定義。

  8. Try catch 似乎也能拿來做 Error log 檔。是的,是這樣用的。但只做 Error log 不夠,仍要處理 exception。

  9. try catch 之後還會裡面的功能還會執行。看是否哪一行有誤。
    10.Recyview 裡面 try catch 異常的話是只有死哪一行還是全死?若不用 try catch 包出來,可以用 Error log 檢查。 try catch 主要是做例外處理,開發階段可以這樣做,營運中不建議。

第八章課程筆記

筆記內容

基本的 Null範例

specify type explicitly: 當你不清楚當前變數的type

在你想要使用的時候,才把實例創建出來

Nullable 變數的賦值以及呼叫規則

Wolf 是null的時候不會賦值給 hunger
也不會執行 eat()

可串接 Nullable的安全呼叫 (?.)

可串接 Nullable的安全賦值 (?.)

wolf 或是 hunger是null的時候
x 就會是 null

貓王運算子(:?)Elvis Operator (?:)


貓王運算子 Elvis Operator (?:)
wolf 或是 hunger是null的時候
y 就會是 -1

可存放 Nullable 型態的陣列

什麼時候會用到 Null

  • 在Kotlin中,Null表示一個變量沒有指向任何物件實例。
    例如從資料庫查詢時,如果沒有查到匹配的結果,可以返回null來表示查詢為空。

  • 表示可能缺少的可選參數

  • 可串接 Nullable的安全呼叫 (?.)

  • 可串接 Nullable的安全呼叫 (?.)

  • 轉換類別的時候可以使用 as? 轉換,避免程式拋出例外

非空斷言運算子(!!)


下了兩個!!表示這不會 null,會發生以下的事

  • 使用時機
    • 你確定變數在此處不可能為 null,但編譯器無法推斷出來。
    • 呼叫 Java 類別或變數時,需要按非 null 變量處理,但編譯器無法推斷。
      • 因為Java除了 primitive type 以外,所有類別實例在宣告時預設為 nullable
    • 在已檢查過不為 null 的情況下,避免多次檢查。
    • 寫測試程式碼的時候用來驗證不可能為 null的情形。

例外的用途

  • 程式在執行的階段(Runtime),發生了預期外的事件,導致例外被拋出(throw)。

處理例外

  • 在 Kotlin中我們可以透過 try / catch / finally 來捕捉並且處理例外

  • 直接在 function 後面輸入 .try 可以觸發 IDE的快捷生成功能

  • try / catch 其實是 Function,所以可以有回傳值

自定義例外

  • 我們也可以使用保留詞 throw主動丟出例外

  • 除了系統提供的例外,我們也可以自定義例外

  • 小試身手
    答案是C

第九章 集合:井然有序

  1. 請問kotlin的set是怎麼判斷加入的元素是否重複的
筆記內容

第九章課程筆記

Agenda

. Array
. List
. Set
. Map

什麼是Array(陣列)

  • Array是一種資料結構,它**保存固定數量的相同類型或其子類型的值。
  • 內容可變
  • 無法改變大小

Array — Create 建立

  • 範例

Array — Access and modify

  • 範例

Array — Operation 操作

  • 範例

List 清單

什麼是List(列表)

  • List按指定順序儲存元素並提供對它們的索引存取。
  • List列表元素(包括空值)可以重複,List以包含任意數量的相等物件或單一物件的出現
  • List是不可變的(所以剛剛array的存取方式就不能用來修改喔!)

List — Create 建立

List — Access


List — Operation 操作




但不能修改的話要怎麼辦呢

什麼是mutableList (可變List)

  • 是List具有特定於清單的寫入操作。
  • 可以操作的List

mutableList — Create 建立


mutableList — CRUD


mutableList — Operation 操作


Set 集合

什麼是set(集合)

  • Set 是儲存獨特的元素;它們的順序通常是未定義的。
  • 元素是唯一的包含null
  • 不可重複
  • 無順序性

Set — Create 建立


那有重複值得話會出錯嗎? 答案是不會出錯,但會把重複的刪除唷

Set — Access

Set — Operation 操作


mutableSet(可變集合)

什麼是mutableSet(可變集合)

  • 是set具有特定於集合的寫入操作。
  • 可以操作的set

mutableSet — CRUD


mutableSet — Operation



Map (字典)

什麼是map

  • Map儲存鍵值對(或目)鍵是唯一的,但不同的鍵可以與相同的值配對。
  • key值是唯一的
  • 無順序性

Map — Create 建立


Map — Access


Map — Operation 操作




mutableMap(可變的Map)

什麼是mutableMap(可變Map)

  • 是Map具有特定於Map的寫入操作。
  • 可以操作的Map

mutableMap — Create 建立

mutableMap — CRUD

mutableMap — Operation 操作


互相轉換的方式


第十章 泛型:見果知因

  • Location: Zoom
  • Date: 2023-10-25 21:00 PM
  • 導讀人: 洪彥彬
  • 簡報連結
  • 影片連結-未完成
  • Host: Gobby
  • Tech Support : 梓育
  • Participants:
    • mamu
    • Gobby
    • 五更琉璃
  • 我有問題想問🙋

  1. 之前好像有看過T,或者K、V,它們跟E差在哪啊?
  2. 什麼是 sealed class? 可以參考這裡
筆記內容

第十章課程筆記

今天不會釋出任何投影片以及程式碼

  • 程式碼以及圖片都來自書上
  • 鼓勵大家手打程碼
  • 書上有程式題目(填空題),對於學習非常有幫助
    • 如何上手程式語言
      • 學習->假設->實驗
      • 多寫
      • 多看
  • 當然還有更好的學習方式

名詞對應表

泛型 Generic
類型參數 Type parameter
協變 Covariance
逆變 Contravariance
  • 泛型是怎麼被使用的?

val x: MutableList<String>

It means that MutableList:

interface MutableList<E> : List<E>, MutableCollection<E>{ fun add(index; Int, element: E): Unit //More code }

所以這邊的E就都會是String

我們來看個範例

fun main(args: Array<String>) { // List, Map var a: List(Int) = listOf<Int>(1,2,3) var i: String = a[0] }

已經定義 E -> Int 之後使用的他都得是 int

fun main(args: Array<String>) { // List, Map var a: Map<Int, Int> = mapOf<Int, Int> ( "a" to 1, "b" to 2, "c" to 3 ) val value: Int? = a[4] // Convention // T -> Type // E -> Element // V -> Value // K -> key I // Q , Z, YY, ABA }

範例: 寵物競賽
// Pet: cats, dogs, fish
// Contest
// Retailer: CatRetailer, DogRetailer, FishRetailer
// Vet

  • 當你使用 Contest<Cat> 可以限制是貓的比賽
  • 當你使用 Contest<Pet> 可以限制是寵物間跨物種的比賽 (Pet 之間有繼承關係)






執行結果:


答案是可以

第二個範例:
前面相同 ,這邊要示範泛型繼承


不能編譯是因為回傳的不同


也就是說
如果把interface改成

就可以用了

Covariant -> out

class或是 interface 的函式有回傳泛型時,或是val屬性為T型別時可以使用這關鍵字

範例三: 新增out

和剛剛一樣

書上的問題

N
Y
N (因為var不行)
Y
Y

範例四: 獸醫
前面都一樣,其中





也就是把上面Vet的class改成

或是

也就是下圖的兩種位置

範例五: 把in 放在關鍵字裡面

Y

N 不能有回傳型別

N 不能有回傳值
不然要改成

N

複習




第十一章 lambda 與高階函式:把程式碼當成資料來處理

  • Location: Zoom
  • Date: 2023-10-25 21:00 PM
  • 導讀人: 林楷祐(Chaos)
  • 簡報連結
  • 影片連結-未完成
  • Host: Gobby
  • Tech Support : 梓育
  • Participants:
    • 五更琉璃
  • 我有問題想問🙋

  1. 那我直接 { a , b -> 1 + 2 } 這樣還需要宣告嗎?還是他會直接過?
    Kotlin 需要型別,無法從上文或下文回推,因此需要顯示函式。
  2. 可以問一下IntelliJ icon plug in套件是哪一套呢?
    截圖 2023-11-01 晚上9.33.05.png
筆記內容

第十一章課程筆記

​​​​![圖片.png](https://hackmd.io/_uploads/SkshhRkQT.png)

大綱

Lambda 基本語法
Lambda 型態
Lambda 呼叫規則
Lambda 與高階函式
Lambda 應用場景
利用 typealias 建立型態別名
更多細節!

Lambda 基本語法

截圖 2023-11-01 晚上9.11.55.png

截圖 2023-11-01 晚上9.12.01.png

截圖 2023-11-01 晚上9.12.35.png

截圖 2023-11-01 晚上9.14.31.png

截圖 2023-11-01 晚上9.22.01.png

截圖 2023-11-01 晚上9.22.11.png

截圖 2023-11-01 晚上9.22.18.png

  • 接收參數不可變 ( Immutable )
  • 單一參數可以忽略參數宣告並使用
  • 唯一參數的隱式名稱 it 存取
  • 利用換行 / 分號來新增述句 ( Statement )

Lambda 型態

截圖 2023-11-01 晚上9.24.06.png

截圖 2023-11-01 晚上9.24.37.png

利用typealias建立型態別名

  • typealias 可以有效地建立命名系統,藉由命名全新型態來消彌
    函式型別語法上的複雜問題

Lambda型態(延伸)

  • 柯里化(Currying):將多個參數的函式/Lambda轉化成接收單一參數的函式,並返回接受餘下參數且返回結果的函式技術
    圖片.png
  • 函式引用(Functioneference)可以使用特殊語法::(雙冒號)將具名函式當作 Lambda 使用
    圖片.png
    圖片.png
    圖片.png
  • 閉包(Closure)
    圖片.png
    圖片.png

第十二章 內建的高階函式:升級你的程式

  • Location: Zoom
  • Date: 2023-11-14 21:00 PM
  • 導讀人: 小夫
  • 簡報連結
  • 影片連結-未完成
  • Host: Gobby
  • Tech Support : 梓育
  • Participants:
    • Gobby
    • David(梓育)
    • 五更琉璃
  • 我有問題想問🙋

筆記內容

第十二章課程筆記

高階函式(Higher-Order Function)

  • 打開類型提示: 為了更清楚之地目前函數的類型和回傳值,建議打開類型提示。

    圖片

今日目錄

  • Min、Max
  • Filter
  • Map
  • ForEach
  • Group
  • Reduce/Fold
    高階函數是一個重要的程式設計概念,它們在許多現代程式語言中都有支援,包括Kotlin、JavaScript和Swift等。高階函數的特點是它們可以接受其他函數作為參數,或者將函數作為結果返回,甚至可以將函數存儲在數據結構中。
    處理基本型態以外的物件,需實做 Comparable 的介面,才可以進行比較。
    圖片
    圖片

Entrust 實作 Comparable 介面

val items = listOf<Entrust>( Entrust(id = "0050", name = "元大台灣50", price = 120.0, volume = 1), Entrust(id = "2330", name = "台積電", price = 500.0, volume = 2), Entrust(id = "00878", name = "國泰永續高股息", price = 20.0, volume = 1), ) val maxResult = items.maxBy { it } // Entrust(id=2330, name=台積電, price=500.0, volume=2) val minResult = items.minBy { it } // Entrust(id=0050, name=元大台灣50, price=120.0, volume=1)
​​​​甚至可以使用比較符號
val entrust1 = items[0] // Entrust(id=0050, name=元大台灣50, price=120.0, volume=1) val entrust2 = items[2] // Entrust(id=00878, name=國泰永續高股息, price=20.0, volume=1) val comparedEntrust = entrust1 > entrust2 // false

建議使用 xxxOrNull 系列

如果列表空的會得到 java.util.NoSuchElementException。
圖片

val items = listOf<Int>() items.min() items.max() ... val items = listOf<Int>() items.maxOrNull() items.maxByOrNull { ... } if (items.isNotEmpty()) { items.max() }

最好使用 xxxOrNull 系列或加入列表不是空的判斷。

Filter、FilterNotNull

​​​​![圖片](https://hackmd.io/_uploads/rkoNQxb46.png)

過濾給予的條件。

val items = listOf(null, 2, 3, 4) val filterResult = items.filter { it != null } // filterResult is [2, 3, 4]
val items = listOf(null, 2, 3, 4) val filterResult = items.filterNotNull() // filterResult is [2, 3, 4]

Map

將原本的內容轉換成另一種結果或類型。

val items = listOf(1, 2, 3, 4) val mapResult = items.map { it.times(10) } // [10, 20, 30, 40]

mapIndexed

跟 map 類似,但多了一個 index,提供第幾個物件的訊息。

val items = listOf(1, 2, 3, 4) val mapResult = items.mapIndexed { index, i -> index to i.times(10) } // [(0, 10), (1, 20), (2, 30), (3, 40)]

mapTo

將轉換的結果,儲存在另外的集合。需要注意的是必須使用可變(Mutable)的類型。

val items = listOf(1, 2, 3, 4) val otherItems = mutableListOf<Int>() val mapResult = items.mapTo(otherItems) { it.times(10) } // otherItems is [10, 20, 30, 40] // mapResult is [10, 20, 30, 40] val isTheSame = mapResult === otherItems // isTheSame is true

flatMap

扁平化轉換,簡單來說就是條件參數放入的類型是依照原本的類型

val items = listOf(1, 2, 3, 4) val innerList = listOf("a", "b", "c") val flatMapResult = items.flatMap { outerItem -> innerList.map { innerItem -> innerItem + outerItem } } // flatMapResult is [a1, b1, c1, a2, b2, c2, a3, b3, c3, a4, b4, c4]

forEach

相似於 for in 的語法,是 Iterable 的擴充函數,沒有回傳值

val items = listOf(1, 2, 3, 4) items.forEach { item -> println(item) } // 1 // 2 // 3 // 4

groupBy

根據條件將目標分群,回傳一個新建立的 Map。
Map 的 Key 是分群時的條件。
Value 是原本目標被分群的元素。

data class Entrust( ... val type: Type ) : Comparable<Entrust> { ... /** * 類型 */ sealed class Type { /** * 股票 */ data object Stock : Type() /** * ETF */ data object ETF : Type() } } val items = listOf<Entrust>( Entrust(id = "0050", name = "元大台灣50", price = 120.0, volume = 1, type = Entrust.Type.ETF), Entrust(id = "2330", name = "台積電", price = 500.0, volume = 2, type = Entrust.Type.Stock), Entrust(id = "00878", name = "國泰永續高股息", price = 20.0, volume = 1, type = Entrust.Type.ETF), ) val result: Map<Entrust.Type, List<Entrust>> = items.groupBy { it.type } /** * { * ETF=[ * Entrust(id=0050, name=元大台灣50, price=120.0, volume=1, type=ETF), * Entrust(id=00878, name=國泰永續高股息, price=20.0, volume=1, type=ETF) * ], * Stock=[ * Entrust(id=2330, name=台積電, price=500.0, volume=2, type=Stock) * ] * } */

Reduce

將集合累進運算後,回傳一個結果

val items = listOf(1, 2, 3, 4) val result = items.reduce() { accumulator: Int, item: Int -> accumulator + item } // 20

Fold

與 Reduce 不同,多了一個初始值。

val items = listOf(1, 2, 3, 4) val result = items.fold(10) { accumulator: Int, item: Int -> accumulator + item } // 20

Closures

closures 的概念與其他一些程式語言中的 lambda expressions 或 anonymous functions 類似。Closures 是一種函數,它可以捕獲和操作其周圍作用域中的變數。
圖片

圖片

Functional (SAM) interfaces

僅具有一個抽象方法的介面稱為 函數介面 或 單一抽象方法介面。
圖片
不使用 SAM
圖片

圖片


附件 i 協同程序:平行執行程式碼

  • Location: Zoom

  • Date: 2023-11-21 21:00 PM

  • 導讀人: Lucien

  • 簡報連結

  • 實作一

  • PPT大綱

  • 影片連結-未完成

  • Host: Gobby

  • Tech Support :

  • Participants:

    • Gobby
    • 五更琉璃
  • 我有問題想問🙋

  • 一個執行緒最多能產生幾個Coroutines呢?是取決於電腦效能嗎?看電腦是幾核心就有幾個執行緒,依 CPU 數量,某種程度是電腦效能,但實際能產生幾個無法回答。

  • 想請問一下剛剛的實作三 為什麼是先執行Tish!Tish!?

附件 1 課程筆記

PPT大綱:
https://lucienhsu.notion.site/0581137d3d1b4b6893f4958ded5bd296?pvs=4

實作一:
https://gist.github.com/Lucien-Hsu/9256f6ed066c23532b1b3729ab8418bd
截圖 2023-11-21 晚上9.11.32

截圖 2023-11-21 晚上9.12.24

截圖 2023-11-21 晚上9.15.43

截圖 2023-11-21 晚上9.17.24

截圖 2023-11-21 晚上9.21.15

截圖 2023-11-21 晚上9.21.42

截圖 2023-11-21 晚上9.24.55

官方文件:
https://kotlinlang.org/docs/coroutines-overview.html

Kotlin 小宇宙:使用 Coroutine 優雅的執行非同步任務 (iThome鐵人賽系列書)
https://www.tenlong.com.tw/products/9786263333796


附件 ii 測試:讓程式碼對自己負責

  • Location: Zoom

  • Date: 2023-11-29 21:00 PM

  • 導讀人: Scolley

  • 簡報連結

  • 影片連結-未完成

  • Host: Gobby

  • Tech Support : 梓育

  • Participants:

  • 我有問題想問🙋

  • 簡報當中測試的參數都是固定的,能否產生不固定的多筆參數進行測試?

附件 2 課程筆記

為什麼要寫測試

圖片
寫測試後,隨著產品開發迭代,整體開發的時間其實反而是比沒寫來得少。

要怎麼寫?怎麼測試?

圖片
傳統上,自動化測試被認為昂貴,且常在特性編寫數月或數年後才進行。文中作者提出測試自動化金字塔的概念,強調單元測試在策略中的基礎地位,提供具體數據給工程師。同時,強調自動用戶界面測試成本高、脆弱且應盡量減少。

​​​​測試重點在強調服務層測試的重要性,該層位於金字塔中間,專注於單獨測試應用程序的服務,填補了單元和用戶界面測試之間的差距。最後組織在測試自動化中經常犯錯的地方是忽視了服務層(應用層)測試,導致測試運行昂貴且容易出錯。

什麼是Unit Test?

你測試原始碼的各個單元
圖片

測試框架: Junit (https://github.com/junit-team/junit5/)

圖片
複製這兩行
圖片

貼到這邊
圖片
利用@Test還有assert就可以測試了(做邊是預期的結果,右邊是實際的行為)
圖片
過了的話就會出現
圖片

或是用以下這種方式

  1. ``
    圖片
  2. DisplayName
    圖片

測試框架: KotlinTest (https://github.com/kotest/kotest)

圖片
https://kotest.io/docs/framework/testing-styles.html

e.g.
圖片
圖片
圖片
可以多個測試(承上圖)
圖片
跑完會看到
圖片

Unit Test 推薦的結構: AAA Pattern

  • Arrange - 初始化物件、要用到的參數 (Precondition)
  • Act - 呼叫要測試的方法 (如果寫PDD的話就是一個行為)
  • Assert - 驗證測試結果
    e.g.
    圖片

Given – When – Then Pattern (User Story)

Formula

  • (Given) some context
  • (When) some action is carried out
  • (Then) a particular set of observable consequences should obtain

Example:
* (Given) 小明有 10元
* (When) 小明買一瓶 5元 的可樂
* (Then) 小明還有5元

圖片
圖片
https://miro.com

附件 iii 本書遺珠:(我們沒有談到的)十大要事

  • Location: Zoom

  • Date: 2023-12-5 21:00 PM

  • 導讀人: 范聖佑

  • 簡報連結

  • 影片連結-未完成

  • Host: Gobby

  • Tech Support : 梓育

  • Participants:

    • 五更琉璃
    • Gobby
  • 我有問題想問🙋

附件3 課程筆記

Kotlin中文開發者大會: https://www.jetbrains.com.cn/lp/kotlin-online-conference/

遺珠十大要事

1.程式包(package)與 import
2.可見範圍修飾符
3.enum類別
4.密封(sealed)類別
5.嵌套與內部類別
6.物件(object)宣告與運算式
7.擴展(extention)
8.return、break與continue
9.其他有趣的函式功能
10.互動能力(interoperability)

程式包(package)與 import

專案其實都是開啟在根目錄,在src底下,但如果我們開始使用別人的lib或是package時,就需要這樣的語法

  • 想解決的問題 => 同名類別在使用時不知道是要用哪個?
    • 大家都是金城武
    • 一人唱名、萬人回頭
  • 解決的方式 => 把類別放在資料夾裡
    • 只好加個城市名當前綴(也就是把大家放到不同的位置下)
    • 用姓氏來區別名字相同的人
      也就是說,這些資料夾其實也視同為這個名稱

圖片

e.g.
圖片
圖片

而上面的import as 就可以大幅度簡短很長的名稱所導致的冗長問題
而且這樣的寫法也能在如果真的發生了在相同資料夾又相同名稱的物件時,可以用來區別
執行結果如下
圖片

Package 與Import帶來的好處

  • 協助組織程式碼
    • 具語義的分類
  • 防止名稱衝突
    • 使用全名具體指定

可見範圍(visibility)修飾符

Top-Level 可見範圍修飾符

圖片

類別/介面 可見範圍修飾符

圖片
e.g
圖片
Animal的id就是puclic
圖片
所以像是這邊繼承的方式如同Otter
圖片
最後我們就可以這樣去使用這兩個class

enum類別

顧名思義就是設定一些東西的選項。

  • 功能
    • 幫變數指定對他來說有效的值
  • 好處
    • 確保變數只會被設為有效的值
    • 仍具有類別的特性,有屬性、有函式、可覆寫

e.g
圖片
圖片

​​​​![圖片](https://hackmd.io/_uploads/rkT9SsnHa.png)
​​​​執行結果
​​​​![圖片](https://hackmd.io/_uploads/rJFsSj2Ba.png)

密封(sealed)類別

  • 功能
    • enum的加強版
    • 可將類別階層限制為特定的子型態集合
  • 好處
    • 可跟when表達式一起用
      e.g.
      圖片
      圖片

嵌套(Nested,巢狀)與內部(Inner)類別

  • 功能

    • 想讓外部的類別擁有不屬於它的主要目的的額外功能
    • 把程式碼放在它被使用的地方附近
      e.g.
      先看Outer
      圖片
      看Nested
      圖片
      看Inner
      圖片

    使用方式
    圖片
    執行結果
    圖片

物件(object)宣告與運算式

  • 功能
    • 確保某個型態只能建立一個實例
  • 條件
    • 不能在宣告式裡加入建構式

e.g (companion object)
圖片
圖片
圖片

擴展(extention)

  • 功能
    • 在既有的類別加入新的函式與屬性
  • 好處
    • 可以在不修改始碼的前提下,擴充原本類別的能力

e.g
圖片
圖片
所以String就多了md5的屬性
圖片
圖片
圖片
使用方式
圖片
或是
圖片
圖片

return、break與continue

  • return: 從函式內跳出
  • break: 終止包住他的圈
  • continue: 前往包住它的圈的下一次送代
    e.g.
    • case1
      圖片
      圖片
    • case2
      圖片
      圖片
    • case3
      圖片
      圖片
    • case4
      圖片
      圖片

其他有趣的函式功能

vararg

  • 功能: 讓Function以受多個參數
  • 好處: 不論對設計者或使用者來說)讓Functio更彈性
  • 條件: 只有一個參數可以標為vararg(通常是最後一個)
    e.g
    圖片
    圖片
    圖片
    圖片

infix

  • 功能: 讓Function可以移除.及()
  • 好處: 讓程式碼看起來更像英文語句
  • 條件
    • 一定要是 member function或extension
    • 一定只有一個參數
    • 參數不可以是vararg也不可以有default值

e.g.
圖片
圖片

inline

  • 功能: 產生的程式碼會移除函式呼叫改成函式的内容
  • 好處: 換效能
  • (可能的)副作用:產生出來的程式碼會變多
    e.g.
    圖片
    圖片
    圖片

互動能力(interoperability)

圖片
如果有這樣的需求
圖片
e.g.
圖片
圖片
圖片

行有餘力想嘗鮮

Select a repo