偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

6個(gè)能讓你的Kotlin代碼庫(kù)更有意思的“魔法糖”

開(kāi)發(fā) 后端
我會(huì)在本文中與你分析我最喜歡的 Kotlin 語(yǔ)法糖,它們是在我需要寫(xiě)簡(jiǎn)潔而魯棒 Android 應(yīng)用程序組件時(shí)發(fā)現(xiàn)的。為了讓這篇文章讀起來(lái)更輕松,我把它分成三個(gè)部分。在這第一部分中,你會(huì)看到密封類(lèi)和 when() 控制流函數(shù)。愉快的開(kāi)始吧!

語(yǔ)法糖會(huì)導(dǎo)致分號(hào)的悲劇。—— Alan J. Perlis

我們不斷地失去一些東西。其中一些東西相對(duì)來(lái)說(shuō)會(huì)更重要,現(xiàn)在重新揀起來(lái)還不算太晚。Kotlin 語(yǔ)言為程序員的生活帶來(lái)了大量新的概念和特性,它們?cè)谌粘i_(kāi)發(fā)中使用起來(lái)會(huì)很困難。我在生產(chǎn)環(huán)境中使用了兩年 Kotlin 之后,才感受到它帶來(lái)的快樂(lè)和滿(mǎn)足。這是怎么發(fā)生的?原因就在那些小小的語(yǔ)法糖中。

我會(huì)在本文中與你分析我最喜歡的 Kotlin 語(yǔ)法糖,它們是在我需要寫(xiě)簡(jiǎn)潔而魯棒 Android 應(yīng)用程序組件時(shí)發(fā)現(xiàn)的。為了讓這篇文章讀起來(lái)更輕松,我把它分成三個(gè)部分。在這第一部分中,你會(huì)看到密封類(lèi)和 when() 控制流函數(shù)。愉快的開(kāi)始吧!

擁抱“模式匹配”的密封類(lèi)

最近我的工作中有機(jī)會(huì)使用 Swift。我不僅要審核代碼,還要將其中一些組件翻譯成 Kotlin 實(shí)現(xiàn)。我讀的代碼越多,就越感到驚訝。最對(duì)我來(lái)說(shuō),最吸引人的特性是枚舉??上?Kotlin 的枚舉并不太靈活,我不得不挖掘合適的替代品: 密封類(lèi) 。

密封類(lèi)在編程界并不是什么新鮮玩意兒。事實(shí)上,密封類(lèi)是一個(gè)非常知名的語(yǔ)言概念。Kotlin 引入了 sealed 關(guān)鍵字,它可用于類(lèi)聲明,表示對(duì)類(lèi)層次結(jié)構(gòu)的限制。某個(gè)值可以是有限類(lèi)型中的一個(gè),但它不能是其它類(lèi)型。簡(jiǎn)單地說(shuō),你可以使用密封類(lèi)來(lái)代替枚舉,甚至做更多事情。

來(lái)看看下面的示例代碼。

 

  1. sealed class Response  
  2. data class Success(val body: String): Response()  
  3. data class Error(val code: Int, val message: String): Response()  
  4. object Timeout: Response() 

乍一看,這些代碼除只是聲明了一些簡(jiǎn)單的繼承關(guān)系,但步步深入,就會(huì)提示一個(gè)諒人的真相。為 Response 類(lèi)添加的 sealed 關(guān)鍵字到底起到了什么作用呢?提示這個(gè)問(wèn)題最好的方法是使用 IntelliJ IDEA Kotlin Bytecode 工具。

6個(gè)能讓你的Kotlin代碼庫(kù)更有意思的“魔法糖”

第一 步。查看 Kotlin 字節(jié)碼 (Kotlin Bytecode)

6個(gè)能讓你的Kotlin代碼庫(kù)更有意思的“魔法糖”

第二步。將 Kotlin 字節(jié)碼反編譯成 Java 代碼

經(jīng)過(guò)這樣非常簡(jiǎn)單地翻譯,你可以看到 Kotlin 代碼對(duì)應(yīng)的 Java 代碼呈現(xiàn)。

 

  1. public abstract class Response { 
  2.    private Response() { 
  3.    } 
  4.  
  5.    // $FF: synthetic method 
  6.    public Response(DefaultConstructorMarker $constructor_marker) { 
  7.       this(); 
  8.    } 

你可能已經(jīng)猜到了,密封類(lèi)專(zhuān)們用于繼承,所以它們是抽象的。不過(guò)他們變得與枚舉相似的?在這里,Kotlin 編譯器做了大量的工作,讓你可以在 when() 函數(shù)中將 Response 的子類(lèi)用作分支。此外,Kotlin 提供了很大的靈活性來(lái)允許對(duì)密封類(lèi)的繼承結(jié)構(gòu)可以被當(dāng)作數(shù)據(jù)聲明甚至對(duì)象來(lái)使用。

 

  1. fun sugar(response: Response) = when (response) { 
  2.     is Success -> ... 
  3.     is Error -> ... 
  4.     Timeout -> ... 

它不僅提供了非常徹底的表達(dá)式,還提供了自動(dòng)類(lèi)型轉(zhuǎn)換,因此你可以在不需要額外的轉(zhuǎn)換的情況下使用 Response 實(shí)例。

 

  1. fun sugar(response: Response) = when (response) { 
  2.     is Success -> println(response.body) 
  3.     is Error -> println("${response.code} ${response.message}"
  4.     Timeout -> println(response.javaClass.simpleName) 

你能想象一下,如果沒(méi)有一個(gè) sealed 的功能,或者根本沒(méi)有 Kotlin ,它可能看起來(lái)是那么的丑陋和復(fù)雜?如果你忘記了 Java 語(yǔ)言的一些特性,請(qǐng)?jiān)俅问褂?IntelliJ IDEA Kotlin Bytecode ,但要坐下來(lái)使用 - 這可能會(huì)讓你暈倒。

 

  1. public final void sugar(@NotNull Response response) { 
  2.    Intrinsics.checkParameterIsNotNull(response, "response"); 
  3.    
  4.    String var3; 
  5.    if (response instanceof Success) { 
  6.       var3 = ((Success)response).getBody(); 
  7.       System.out.println(var3); 
  8.    } else if (response instanceof Error) { 
  9.       var3 = "" + ((Error)response).getCode() + ' ' + ((Error)response).getMessage(); 
  10.       System.out.println(var3); 
  11.    } else { 
  12.       if (!Intrinsics.areEqual(response, Timeout.INSTANCE)) { 
  13.          throw new NoWhenBranchMatchedException(); 
  14.       } 
  15.  
  16.       var3 = response.getClass().getSimpleName(); 
  17.       System.out.println(var3); 
  18.    } 

總結(jié)一下,我很高興在這種情況下使用 sealed 關(guān)鍵字,因?yàn)樗屛乙灶?lèi)似于 Swift 的方式塑造我的 Kotlin 代碼。

使用 when()函數(shù)來(lái)排列

由于你已經(jīng)看到了 when()在 sealed 類(lèi)中的用法,我決定再分享更多強(qiáng)大的功能。 想象一下,你必須實(shí)現(xiàn)一個(gè)接受兩個(gè) enums 并產(chǎn)生一個(gè)不可變狀態(tài)的函數(shù)。

 

  1. enum class Employee { 
  2.     DEV_LEAD, 
  3.     SENIOR_ENGINEER, 
  4.     REGULAR_ENGINEER, 
  5.     JUNIOR_ENGINEER 
  6.  
  7. enum class Contract { 
  8.     PROBATION, 
  9.     PERMANENT, 
  10.     CONTRACTOR, 

enum class Employee 描述了在公司 XYZ 中可以找到的所有角色, enum class Contract 包含所有類(lèi)型的雇傭合同。 基于這兩個(gè) enums ,你應(yīng)該返回一個(gè)正確的 SafariBookAccess 。 而且,你的函數(shù)必須產(chǎn)生給定 enum 的所有排列的狀態(tài)。 第一步,我們來(lái)創(chuàng)建狀態(tài)生成函數(shù)的簽名。

 

  1. fun access(employee: Employee, 
  2.            contract: Contract): SafariBookAccess 

現(xiàn)在是時(shí)候定義 SafariBooksAccess 結(jié)構(gòu)體了,因?yàn)槟阋蚜私?sealed 關(guān)鍵字,這是使用它最適合的時(shí)機(jī)。封裝 SafariBookAccess 并不是必須的,但它是封裝不同情景下的 SafariBookAccess 的不同狀態(tài)的好方式。

 

  1. sealed class SafariBookAccess  
  2. data class Granted(val expirationDate: DateTime) : SafariBookAccess()  
  3. data class NotGranted(val error: AssertionError) : SafariBookAccess()  
  4. data class Blocked(val message: String) : SafariBookAccess() 

那么隱藏在 access() 函數(shù)后面的主要意圖是什么?全排列!讓我們羅列下。

 

  1. fun access(employee: Employee, 
  2.            contract: Contract): SafariBookAccess { 
  3.     return when (employee) { 
  4.         SENIOR_ENGINEER -> when (contract) { 
  5.             PROBATION -> NotGranted(AssertionError("Access not allowed on probation contract.")) 
  6.             PERMANENT -> Granted(DateTime()) 
  7.             CONTRACTOR -> Granted(DateTime()) 
  8.         } 
  9.         REGULAR_ENGINEER -> when (contract) { 
  10.             PROBATION -> NotGranted(AssertionError("Access not allowed on probation contract.")) 
  11.             PERMANENT -> Granted(DateTime()) 
  12.             CONTRACTOR -> Blocked("Access blocked for $contract."
  13.         } 
  14.         JUNIOR_ENGINEER -> when (contract) { 
  15.             PROBATION -> NotGranted(AssertionError("Access not allowed on probation contract.")) 
  16.             PERMANENT -> Blocked("Access blocked for $contract."
  17.             CONTRACTOR -> Blocked("Access blocked for $contract."
  18.         } 
  19.         else -> throw AssertionError() 
  20.     } 

這個(gè)代碼很完美,但你能讓它更像 Kotlin 嗎?當(dāng)你每天對(duì)同事的 PR/MR 進(jìn)行審查時(shí)會(huì)有什么建議嗎?你可能會(huì)寫(xiě)一些這樣的評(píng)論:

  • 太多 when() 函數(shù)。使用 Pair 來(lái)避免嵌套。
  • 改變枚舉參數(shù)的順序,定義 Pair() 對(duì)象來(lái)讓它更易讀。
  • 合并重復(fù)的 return。
  • 改為一個(gè)表達(dá)式函數(shù)。

 

  1. fun access(contract: Contract, 
  2.            employee: Employee) = when (Pair(contract, employee)) { 
  3.     Pair(PROBATION, SENIOR_ENGINEER), 
  4.     Pair(PROBATION, REGULAR_ENGINEER), 
  5.     Pair(PROBATION, JUNIOR_ENGINEER) -> NotGranted(AssertionError("Access not allowed on probation contract.")) 
  6.     Pair(PERMANENT, SENIOR_ENGINEER), 
  7.     Pair(PERMANENT, REGULAR_ENGINEER), 
  8.     Pair(PERMANENT, JUNIOR_ENGINEER), 
  9.     Pair(CONTRACTOR, SENIOR_ENGINEER) -> Granted(DateTime(1)) 
  10.     Pair(CONTRACTOR, REGULAR_ENGINEER), 
  11.     Pair(CONTRACTOR, JUNIOR_ENGINEER) -> Blocked("Access for junior contractors is blocked."
  12.     else -> throw AssertionError("Unsupported case of $employee and $contract"

現(xiàn)在它看起來(lái)更整潔,但 Kotlin 還有語(yǔ)法糖可以完全省略對(duì) Pair 的定義。棒!

 

  1. fun access(contract: Contract, 
  2.            employee: Employee) = when (contract to employee) { 
  3.     PROBATION to SENIOR_ENGINEER, 
  4.     PROBATION to REGULAR_ENGINEER -> NotGranted(AssertionError("Access not allowed on probation contract.")) 
  5.     PERMANENT to SENIOR_ENGINEER, 
  6.     PERMANENT to REGULAR_ENGINEER, 
  7.     PERMANENT to JUNIOR_ENGINEER, 
  8.     CONTRACTOR to SENIOR_ENGINEER -> Granted(DateTime(1)) 
  9.     CONTRACTOR to REGULAR_ENGINEER, 
  10.     PROBATION to JUNIOR_ENGINEER, 
  11.     CONTRACTOR to JUNIOR_ENGINEER -> Blocked("Access for junior contractors is blocked."
  12.     else -> throw AssertionError("Unsupported case of $employee and $contract"

這個(gè)結(jié)構(gòu)讓我的生活變得輕松,也讓 Kotlin 代碼讀寫(xiě)變得容易,我希望你也覺(jué)得這很有用。但它是不是不能用于三元組呢?答案是肯定的。

  1. Triple(enum1, enum2, enum3) == enum1 to enum2 to enum3 

以上就是第 1 部分的全部?jī)?nèi)容,如果你仍然很有興趣,請(qǐng)繼續(xù)閱讀第 2 部分。干杯!

責(zé)任編輯:未麗燕 來(lái)源: 開(kāi)源中國(guó)翻譯文章
相關(guān)推薦

2021-02-20 16:01:26

Github前端開(kāi)發(fā)

2020-12-12 13:50:16

云開(kāi)發(fā)

2018-06-24 16:39:28

Tomcat異常線程

2021-01-27 13:54:05

開(kāi)發(fā)云原生工具

2021-06-10 08:15:49

CSS 文字動(dòng)畫(huà)技巧

2021-10-28 19:35:02

代碼main方法

2021-03-25 06:12:55

SVG 濾鏡CSS

2012-05-22 10:12:59

jQuery

2022-08-15 22:34:47

Overflow方向裁切

2022-06-15 07:21:47

鼠標(biāo)指針交互效果CSS

2023-05-15 09:16:18

CSSCSS Mask

2017-08-01 00:52:07

kafka大數(shù)據(jù)消息總線

2013-08-28 09:46:09

Debian LinuLinux發(fā)行版

2012-06-19 16:49:19

Web開(kāi)發(fā)

2024-03-18 08:14:07

SpringDAOAppConfig

2022-07-11 13:09:26

mmapLinux

2009-08-26 17:53:31

C# DropDown

2015-10-28 13:57:29

融合架構(gòu)華三UIS

2010-04-09 11:24:59

Oracle 排序

2021-11-17 10:45:58

Chrome 95新特性前端
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)