本書介紹了Kotlin的基本語法、常用類型、面向對象編程以及一些高階的知識。在所有的章節(jié)中,都廣泛使用圖片和會話的介紹方式,以幫助大腦更容易理解和獲取信息。此外還有各種生動的實例、習題,以及有問必答環(huán)節(jié)。讓讀者仿佛置身其中,更加高效專注地學習知識,而把一些無關緊要的事情拋之腦后。本書以類似于“劃重點”或“記筆記”的方式對某些內容或代碼進行注解和說明,讀者更容易知曉內容和代碼的重要部分。此外,有問必答環(huán)節(jié)的設計也十分巧妙,它會囊括一些在文中沒有提及到,但讀者可能會疑惑的問題
引子 xxi
1 開始:快速入門 1
2 基本類型和變量:關于變量 31
3 函數:跳出主函數 59
4 類和對象:初步認識類 91
5 子類和父類:使用繼承 121
6 抽象類和接口:重要的多態(tài) 155
7 數據類:處理數據 191
8 空值和異常:使代碼安然無恙 219
9 集合:變得有條理 251
10 泛型:從輸出推斷輸入 289
11 lambda和高階函數:像數據一樣使用代碼 325
12 內置高階函數:使你的代碼更強大 363
附錄i 協(xié)程:并行地執(zhí)行代碼 397
附錄ii 測試:確保你的代碼可以運行 409
附錄iii 其他:我們沒有涉及的十大內容 419
詳細目錄
引子
你的大腦與Kotlin。你想學些新東西,但你的大腦總是幫倒忙,讓學習無法繼續(xù)。你的大腦在想:“最好留出空間來記住那些更重要的事情,比如要避開哪些野生動物!蹦敲,該如何哄騙你的大腦,讓它認為如果不知道Kotlin你將無法生存?
誰適合看本書 xxii
我們知道你們在想什么 xxiii
我們知道你的大腦在想什么 xxiii
元認知:思考何為思考 xxv
我們是這樣做的 xxvi
重要說明 xxviii
技術審校團隊 xxx
致謝 xxxi
1 開始
快速入門
Kotlin正在掀起新的浪潮。
自首次發(fā)布以來,Kotlin就以其友好的語法,簡潔、靈活和強大的功能給程序員留下了深刻的印象。在本書中,我們將教你如何構建自己的Kotlin應用程序。我們將從創(chuàng)建并運行基本的應用程序開始講解。在此過程中,你將了解Kotlin的一些基本語法,例如基本語句、循環(huán)以及條件分支。你的旅程剛剛開始。
能夠自由選擇編譯平臺意味著Kotlin可以運行于服務器、云平臺、瀏覽器、移動設備……
歡迎來到Kotlin之城 2
你幾乎可以在任何地方使用Kotlin 3
本章內容 4
安裝IntelliJ IDEA 7
構建一個基本的應用程序 8
你的第一個Kotlin項目 11
新增一個Kotlin文件 12
main函數剖析 13
將main函數添加至App.kt文件 14
你可以在main函數里面做些什么呢 16
循環(huán) 17
循環(huán)示例 18
條件分支 19
帶有返回值的if語句 20
更新main函數 21
使用Kotlin的交互式shell 23
你可以在REPL中加入多行代碼片段 24
Kotlin工具箱 30
2 基本類型和變量
關于變量
所有代碼都依賴于——變量
本章我們將進一步探索Kotlin,并且向你展示Kotlin變量是如何工作的。你會學習Kotlin的基本類型,例如整型(Int)、浮點型(Float)和布爾型(Boolean),并且學習Kotlin的編譯器是如何聰明地從給定的變量值推測出變量類型的。你還將學會如何使用String模板和簡短的代碼來構建復雜的String類型,并且學會創(chuàng)建數組來存儲多個值。最后,你會發(fā)現對象對于Kotlin之城如此重要的原因。
你的代碼需要變量 32
當你聲明變量時會發(fā)生什么 33
變量保存了指向對象的引用 34
Kotlin的基本類型 35
如何顯式聲明變量類型 37
根據變量類型正確賦值 38
將一個變量值賦給另一個變量 39
類型轉換 40
數值類型轉換背后發(fā)生了什么 41
小心溢出 42
使用數組存放多個值 45
創(chuàng)建Phrase-O-Matic應用程序 46
向PhraseOMatic.kt中添加代碼 47
編譯器從數組中元素的值來推測數組的類型 49
var表示該變量可以指向不同數組 50val
表示該變量永遠指向同一個數組 51
Kotlin工具箱 58
3 函數
跳出主函數
現在,是時候更上一層樓了。下面,我們一起來了解一下函數。
到目前為止,你一直將所有的代碼寫在應用程序的主函數中。但是,如果你想要編寫更有條理并且更加易于維護的代碼,你需要知道如何將代碼拆分為不同的函數。在本章中,你將通過構建一個游戲來學習如何編寫函數以及與應用程序交互。你將了解如何編寫簡明的單個表達式函數。在此過程中,你還將學習如何使用強大的for循環(huán)來遍歷范圍和集合。
我們一起來編寫一個游戲“Rock、Paper、Scissors” 60
游戲設計概覽 61
讓程序選擇一個選項 63
如何創(chuàng)建函數 64
可以向函數中傳入多個值 65
可以從函數中返回一個值 66
單個表達式函數 67
向Game.kt中添加getGameChoice函數 68
getUserChoice函數 75
for循環(huán)工作原理 76
詢問用戶的選擇 78
驗證用戶的輸入 81
更強大的布爾表達式 81
向Game.kt中添加getUserChoice函數 83
向Game.kt中添加printResult函數 87
Kotlin工具箱 89
4 類和對象
初步認識類
現在是時候了解一下Kotlin基本類型之外的類型了。
Kotlin的基本類型遲早會難以滿足你的需求,此時,你就需要類的幫助。類是一個模板,它允許你創(chuàng)建自己的對象類型,并定義它們的屬性和函數。這里,你將要學習如何設計、定義類以及如何使用類來創(chuàng)建新的對象。你將會看到構造函數、初始化程序塊、getter和setter,以及getter和setter是如何保護類的屬性的。最后,你將學習Kotlin是如何內置數據隱藏功能,從而節(jié)省你的時間、精力和編碼量的。
使用類定義對象類型 92
如何設計自己的類 93
一起定義一個Dog類 94
如何創(chuàng)建Dog對象 95
如何訪問屬性及函數 96
創(chuàng)建一個Songs應用 97
神奇的對象創(chuàng)建 98
對象是如何創(chuàng)建的 99
現象背后:調用Dog構造函數 100
深入了解屬性 105
靈活的屬性初始化 106
如何使用初始化塊 107
你必須初始化所有屬性 108
如何驗證屬性值 111
如何編寫自定義的getter 112
如何編寫自定義的setter 113
Dogs項目的完整代碼 115
Kotlin工具箱 120
5 子類和父類
使用繼承
你是否曾經想過,只需要做一點點改變,對象的類型就會變得完美?
是的,這就是繼承的好處之一。在本章,你將學習如何創(chuàng)建子類,以及繼承父類的屬 性和方法。你將學會如何覆蓋(override)屬性和方法,從而使類表現出你想要的行 為,并弄清楚什么時候這樣做是合適的(或不合適的)。最后,你將學會如何利用繼 承避免代碼重復,如何利用多態(tài)提高代碼靈活性。
繼承幫助你避免代碼重復 122
我們將要做什么 123
設計一個animal類繼承結構 124
使用繼承避免子類中的代碼重復 125
子類應該覆蓋什么 126
我們可以將一些動物分類 127
添加Canine和Feline類 128
使用IS-A測試類的層次結構 129
繼承樹中的任意子類都滿足IS-A測試 130
創(chuàng)建一些Kotlin動物 133
使用open關鍵字聲明父類及它的屬性和方法 134
子類是如何繼承父類的 135
如何(以及何時)覆蓋屬性 136
覆蓋屬性不僅僅讓你可以指定默認值 137
如何覆蓋方法 138
被覆蓋的方法或屬性仍然是open的 139
向Animals項目中添加Hippo類 140
添加Canine和Wolf類 143
哪個方法被調用了 144
當你調用方法時,變量指向對象的方法進行響應 146
你可以使用父類型作為方法的參數和返回值類型 147
更新后的Animals代碼 148
Kotlin工具箱 153
6 抽象類和接口
重要的多態(tài)
父類繼承層次結構只是一個開始。
如果想充分利用多態(tài),你需要設計抽象類和接口。在本章中,你將學習如何使用抽象 類來控制層次結構中的類能否被實例化。你將知道它們如何強制具體的子類提供自己 的實現。你將了解如何使用接口在相互獨立的類之間共享行為。在此過程中,你將了 解is、as和when的來龍去脈。
再談Animal類的層次結構 156
一些類不能被實例化 157
抽象還是具體 158
抽象類可以有抽象屬性和方法 159
Animal類有兩個抽象方法 160
如何實現一個抽象類 162
你必須實現所有的抽象屬性和方法 163
更新Animals項目 164
獨立的類可以有共同的行為 169
接口可以讓你在父類層次結構之外定義共同的行為 170
讓我們定義Roamable接口 171
如何定義接口屬性 172
聲明一個類實現了一個接口 173
如何實現多個接口 174
如何決定是創(chuàng)建類、子類、抽象類還是接口 175
更新Animals項目 176
接口讓你可以使用多態(tài) 181
在哪里使用is操作符 182
使用when將變量和一組選項進行比較 183
is操作符通常會進行智能轉換 184
使用as進行顯式轉換 185
更新Animals項目 186
Kotlin工具箱 189
7 數據類
處理數據
沒人愿意花費比生精力重新造輪子。
大多數應用程序都包含一些主要用于存儲數據的類。為了使你的編程生活更輕松, Kotlin開發(fā)者提出了數據類的概念。在這里,你將學習如何使用數據類編寫更加 清晰、簡潔的代碼。你將探索數據類工具函數,并學會如何將一個數據對象解構 成它的組件。在此過程中,你將了解默認參數值如何使代碼更靈活。最后將為你
介紹Any,它是所有父類的起源。
==調用了equals方法 192
equals繼承自Any父類 193
Any類定義的共有行為 194
我們可能希望用equals檢查兩個對象是否等價 195
數據類允許你創(chuàng)建數據對象 196
數據類覆蓋了它們繼承的行為 197
使用copy方法復制數據對象 198
數據類定義了componentN方法 199
創(chuàng)建Recipes項目 201
生成的方法僅包含構造函數中定義的屬性 205
初始化許多屬性可能會導致煩瑣的代碼 206
如何在構造函數中設置默認值 207
方法也可以使用默認值 210
重載方法 211
更新Recipes項目 212
Kotlin工具箱 217
8 空值和異常
使代碼安然無恙
每個人都想編寫安全的代碼。
好消息是Kotlin的設計本身就是代碼安全的。我們首先為你展示Kotlin如何使用可空類 型,這意味著你在Kotlin小城逗留期間幾乎不會遇到空指針異常。你將學習如何進行安 全調用,以及如何使用Kotlin的Elvis操作符避免驚慌失措。當我們介紹完空值后,你將 學會如何像專業(yè)人士那樣拋出和捕獲異常。
從變量中刪除對象引用 220
用空值刪除一個對象引用 221
你可以在任何能夠使用非可空類型的地方使用可空類型 222
創(chuàng)建一個可空類型的數組 223
訪問可空類型的方法和屬性 224
通過安全調用確保一切安全 225
鏈式安全調用 226
你可以使用安全調用賦值 228
如果變量的值不為空,使用let執(zhí)行代碼 231
對數組項使用let 232
替代if表達式 233
使用!!操作符故意拋出NullPointerException 234
創(chuàng)建Null Values項目 235
在異常情況下拋出異常 239
使用try/catch捕獲異常 240
使用finally去做無論如何你都想做的事情 241
異常是Exception類型的對象 242
你可以顯式地拋出異常 244
try和throw都是表達式 245
Kotlin工具箱 250
9 集合
變得有條理
你想過比數組更靈活的東西嗎?
Kotlin有一些好用的集合類可以讓你在存儲和管理對象組方面有更多的靈活性和更強的 控制力。你想要可以不斷增加對象的可變列表嗎?你想要排序、打亂和倒序列表的內 容嗎?你想要通過名字進行檢索嗎?或者你想要不動一根手指就實現自動去重嗎?只 要你對以上任何一個功能感興趣,或者想要發(fā)掘更多有意思的功能,請繼續(xù)讀下去。 在本章你將找到答案。
有用的數組 252
數組不能處理的事情 253
Kotlin標準庫 254
List、Set和Map 255
奇妙的List 256
創(chuàng)建MutableList 257
移除一個值 258
改變元素順序以及批量更改 259
創(chuàng)建Collections項目 260
List允許重復項 263
如何創(chuàng)建Set 264
Set如何查重 265
哈希碼與相等性 266
覆蓋hashCode和equals的規(guī)則 267
如何使用MutableSet 268
復制MutableSet 269
更新Collections項目 270
Map的表演時間 276
如何使用Map 277
創(chuàng)建MutableMap 278
從MutableMap移除條目 279
拷貝Map和MutableMap 280
完整的Collections項目代碼 281
Kotlin工具箱 287
10 泛型
從輸出推斷輸入
人人都喜歡通用的代碼。
使用泛型是令代碼一致且不易出錯的一種策略。在本章中,我們將看到Kotlin的集合類
如何利用泛型避免將Cabbage對象放入List。你將了解編寫泛型類、接口和函 數的場景和方法,以及如何將泛型類型限制為特定的父類型。最后,你將學習利用協(xié) 變和逆變控制泛型類型的行為。
泛型在集合中的使用 290
如何定義MutableList 291
在MutableList中使用類型參數 292
通過泛型類或接口可以做什么 293 接下來要做的事 294
創(chuàng)建Pet類的層次結構 295
定義Contest類 296
添加scores屬性 297
創(chuàng)建getWinners方法 298
創(chuàng)建一些Contest對象 299
創(chuàng)建Generics項目 301
Retailer層次結構 305
定義Retailer接口 306
輕松創(chuàng)建CatRetailer、DogRetailer和FishRetailer等對象 307 用out使泛型類型協(xié)變 308
更新Generics項目 309
再定義一個Vet類 313
創(chuàng)建Vet對象 314
用in使泛型類型逆變 315
泛型類型的局部逆變 316
更新Generics項目 317
Kotlin工具箱 324
11 lambda和高階函數
像數據一樣使用代碼
你想要寫出更強大、更靈活的代碼嗎?
如果是的,那么讓lambda來幫助你吧。一個lambda(或者lambda表達式)是像對象一 樣能被傳遞的代碼塊。在本章中,你將了解如何定義lambda,將它賦予某個變量,然 后執(zhí)行其中的代碼。你將學習利用函數類型在高階函數中使用lambda作為參數或者返 回值。最終,你將見證小小的語法糖給寫代碼帶來的樂趣。
初識lambda 326
lambda的代碼格式 327
將lambda賦值給變量 328
調用lambda時會發(fā)生什么 329
lambda表達式類型 331
lambda參數類型的自動解析 332
根據變量類型使用正確的lambda 333
創(chuàng)建Lambdas項目 334
將lambda作為函數參數 339
在函數體中調用lambda 340
代碼運行時發(fā)生了什么 341
將lambda移到函數括號外面 343
更新Lambdas項目 344
函數可以返回一個lambda 347
將lambda作為函數參數和返回值 348
如何使用combine函數 349
用typealias為已存在的類型取別名 353
更新Lambdas項目 354
Kotlin工具箱 361
12 內置高階函數
使你的代碼更強大
Kotlin提供完整的內置高階函數庫。
本章我們將介紹一些最常用的高階函數。你將見到靈活的過濾器家族,并了解它們如 何幫你剪裁集合。你將學會如何用map對集合進行轉換,用forEach對集合進行遍歷, 以及用groupBy對集合元素進行分組。甚至依靠fold用一行代碼完成復雜的計算。學完 本章,你的編程能力將比你想象的更厲害。
Kotlin的內置高階函數 364
用min和max函數處理基礎類型 365
深入理解minBy和maxBy的lambda參數設置 366
sumBy與sumByDouble函數 367
創(chuàng)建Groceries項目 368
走近filter函數 371
使用map轉換集合 372
代碼運行時發(fā)生了什么 373
像for循環(huán)的forEach 375
forEach沒有返回值 376
更新Groceries項目 377
使用groupBy劃分集合 381
在鏈式調用中使用groupBy 382
如何使用fold函數 383
fold函數背后的故事 384
再舉幾個fold函數的例子 386
更新Groceries項目 387
Kotlin工具箱 394
附錄i 協(xié)程
并行地執(zhí)行代碼
有些任務最好在后臺執(zhí)行。
如果你想要從一個慢速的外部服務器讀取數據,你可能不希望其余代碼處于空閑狀態(tài),等待讀取任務的完成。在這種情況下,協(xié)程(coroutine)將成為你新的死黨,它可以讓代碼異步執(zhí)行。這意味著更少的空閑狀態(tài),更好的用戶體驗,而且可以使你的應用程序易于擴展。繼續(xù)往下閱讀,你將學習其中的秘訣:如何在與Bob交談的同時又傾聽Suzy。
附錄ii 測試
確保你的代碼可以運行
眾所周知好的代碼是可以支行的。
但是,你所做的任何修改都有可能引入新的錯誤,阻止你的代碼正常運行。這就是全面測試如此重要的原因:這意味著你能夠在代碼部署到生產環(huán)境之前,知曉其中的任何問題。在本附錄中,我們將討論JUnit和KotlinTest,你可以使用這兩個庫進行單元測試,保障代碼安全。
附錄iii 其他
我們沒有涉及的十大內容
除此之外,還有更多需要學習。
盡管我們已經學習了很多知識,然而還是有很多內容未被包含在本書中。 我們認為還有一些知識點是你需要掌握的。忽略這些內容是我們的不對,然而我們真的很想為你呈現一本能夠輕松上手的書。在你放下本書之前,還請仔細閱讀這些花絮。
1. 包和導入 416
2. 可見性修飾符 418
3. 枚舉類 420
4. 密封類 422
5. 嵌套類和內部類 424
6. 對象聲明和表達式 426
7. 擴展 429
8. return、break和continue 430
9. 更多關于函數的知識 432
10. Kotlin和其他語言的互操作性 434