Kotlin的密封(Sealed)類:超強的枚舉(KAD 28)

来源:http://www.cnblogs.com/figozhg/archive/2017/07/02/7107053.html
-Advertisement-
Play Games

原作者,介紹Kotlin中密封類。這些新概念讓您更接近函數式編程成為可能。 ...


作者:Antonio Leiva

時間:Jun 27, 2017

原文鏈接:https://antonioleiva.com/sealed-classes-kotlin/

 

 

Kotlin的封裝類是Java中沒有的新概念,併為此開闢了另一片可能性新的世界。

 

密封類允許你表達約束層次結構,其中對象只能是給定類型之一

 

 

也就是說,我們有一個具有特定數量的子類的類。最後,我們得到的結論是非常類似枚舉的概念。所不同的是,在枚舉中,我們每個類型只有一個對象;而在密封類中,同一個類可以擁有幾個對象。

 

 

這種差異允許密封類的對象可以保持狀態這給我們帶來一些的優勢(稍後會看到),它也為函數性概念敞開大門。

 

 

怎樣使用密封類

 

 

 

實際上,實現密封類很簡單。讓我們來看一組能夠應用於整數操作的例子。

 

 

實現情況如下:

 

1 sealed class Operation {
2     class Add(val value: Int) : Operation()
3     class Substract(val value: Int) : Operation()
4     class Multiply(val value: Int) : Operation()
5     class Divide(val value: Int) : Operation()
6 }

 

 

我們創建一個名為Operation的密封類,它包含四種操作:加法,減法,乘法和除法。

 

 

這一好處是,現在when表達式要求我們為所有可能的類型提供分支:

 

1 fun execute(x: Int, op: Operation) = when (op) {
2     is Operation.Add -> x + op.value
3     is Operation.Substract -> x - op.value
4     is Operation.Multiply -> x * op.value
5     is Operation.Divide -> x / op.value
6 }

 

 

如果你離開任何一個子類,when會抱怨其不會編譯如果你實現它們,你不需要else語句。通常,由於我們確信我們對所有人都做正確的事情,不推薦這樣做。

 

 

因為它會在編譯時失敗,並且不會運行,如果你決定添加新操作,這樣做也非常好。現添加一對操作,增量和減量:

 

1 sealed class Operation {
2     ...
3     object Increment : Operation()
4     object Decrement : Operation()
5 }

 

 

現在,你會看到編譯器警告你,存在一個問題。只需為這些新操作添加分支:

 

1 fun execute(x: Int, op: Operation) = when (op) {
2     ...
3     Operation.Increment -> x + 1
4     Operation.Decrement -> x - 1
5 }

 

 

你可能已經註意到我做了不同的事情。我使用對象而不是類。這是因為如果一個子類不保持狀態,它只能是一個對象。你為該類創建的所有實例將完全相同,它們不能有不同的狀態。

 

那麼,在when表達式中,對那些情況你可以擺脫is。在這裡,因為只有一個實例,你只能比較對象,你不需要檢查對象的類型。如果為那些,你也可以保留is,它也能工作。

 

 

如果你仔細考慮一下,所有子類都是對象的密封類與枚舉相同。

 

 

將副作用移到單點上

 

 

 

函數編程的副作用是一個非常通用概念。函數編程在很大程度上依賴於給定的功能,相同的參數將返回相同的結果

 

 

任何修改狀態都可能會破壞這一假設。但是任何程式都需要更改狀態,與輸入/輸出元素進行通訊等。因此,重要的是如何在我們的代碼中發現這些操作,並很容易隔離到特定地方。

 

例如,在Android視圖上實現的任何操作都被視為副作用,因為視圖的狀態修改,而函數不知道。

 

我們可以創建一個密封類,使我們能夠對視圖進行操作。基於這個概念,以前的例子:

 

 1 sealed class UiOp {
 2     object Show: UiOp()
 3     object Hide: UiOp()
 4     class TranslateX(val px: Float): UiOp()
 5     class TranslateY(val px: Float): UiOp()
 6 }
 7 
 8 fun execute(view: View, op: UiOp) = when (op) {
 9     UiOp.Show -> view.visibility = View.VISIBLE
10     UiOp.Hide -> view.visibility = View.GONE
11     is UiOp.TranslateX -> view.translationX = op.px
12     is UiOp.TranslateY -> view.translationY = op.px
13 }

 

 

記住:因為我們不需要不同的實例,沒有狀態的操作就可以是對象。

 

 

現在,你可以創建一個Ui對象,彙集要在視圖上做的所有介面操作,直到我們需要時,才執行它。

 

 

我們將描述我們想要做什麼,然後我們可以創建一個執行它們的組件:

 

1 class Ui(val uiOps: List = emptyList()) {
2     operator fun plus(uiOp: UiOp) = Ui(uiOps + uiOp)
3 }

 

 

Ui類存儲操作列表,並指定一個累加和運算符,這將有助於使所有內容更清晰,更易於閱讀。現在我們可以指定要執行的操作列表:

 

1 val ui = Ui() +
2         UiOp.Show +
3         UiOp.TranslateX(20f) +
4         UiOp.TranslateY(40f) +
5         UiOp.Hide
6 
7 run(view, ui)

 

 

 

然後運行它。這裡我只是使用一個run函數,但如果需要,這可以是一個完整的類。

1 fun run(view: View, ui: Ui) {
2     ui.uiOps.forEach { execute(view, it) }
3 }

 

 

想象一下這些,現在你所做的一切都是按順序運行的,但是這可能會很複雜。

 

 

run函數可以傳遞給另一個函數或類,並且那些操作的運行方式將是完全可互換的記住你可以將函數作為參數傳遞

 

 

結論

 

 

密封類的概念非常簡單,但是如果您之前沒有使用函數式編程,則需要一些使用新概念的基礎。

 

 

我必須說,由於我在函數式編程方面的知識限制,我還沒有最大限度的使用密封類。

 

 

如果您像我一樣熱衷於此,我建議你查看以前的文章,您可以在其中瞭解更多有關Kotlin信息,或者在本書中瞭解如何使用Kotlin從頭開始創建一個完整的Android應用程式

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

val ui = Ui() +

        UiOp.Show +

        UiOp.TranslateX(20f) +

        UiOp.TranslateY(40f) +

        UiOp.Hide

 

run(view, ui)


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 多態(Polymorphism)按字面的意思就是“多種狀態”,同樣的行為(方法)在不同對象上有不同的狀態。在OOP中很多地方都要用到多態的特性,比如同樣是點擊滑鼠右鍵,點擊快捷方式、點擊桌面空白處、點擊任務欄等彈出的菜單都是不同的。 ...
  • 很多人在進入學習前端的時候(包括我自己),除了選擇學習合適的技術,還需要一個得(自)心(己)應(喜)手(歡)的開發工具,一個得心應手的開發工具除了可以令你的效率大大提高,也可以令你在寫代碼的時候,心情舒暢 O(∩_∩)O。 我的第一個前端開發工具就是Sublime Text ,說一說我對它的理解吧。 ...
  • 在字面量方式中,我們//之間包起來的所有的內容都是元字元,有的具有特殊意義,大部分都是代表本身含義的普通的元字元 為瞭解決上述想在正則裡面加上一個變數這樣的需求,我們只能使用實例創建的方式了 var reg = new RegExp("^\\d+"+name+"\\d+$","g") 字面量方式和實 ...
  • function busUpLoadImg(postUrl,id) { .......//省略部分不用修改 uploader.on('uploadSuccess', function(file) { $('#' + file.id).addClass('upload-state-done'); //... ...
  • 手機號碼: 電子郵箱: 身份證: 銀行卡: ...
  • 廢話不多說,直接進入主題,margin相關技巧。 1、設置元素水平居中:margin:x auto; 2、margin負值讓元素位移及邊框合併。 外邊距合併 指當兩個垂直外邊距相遇時,它們將形成一個外邊距。合併後的外邊距的高度等於兩個發生合併的外邊距的高度中的較大者。 解決外邊距合併的方法: a、使 ...
  • 這周末在家呆了兩天,正好中午閑暇時間繼續分享Angularjs相關,今天主要分享Angularjs總體介紹及數據綁定部分內容,下麵直接進入主題。 1、基本概念: AngularJS是為了剋服HTML在構建應用上的不足而設計的。HTML是一門很好的偽靜態文本展示設計的聲明式語言,但要構建WEB應用的話 ...
  • 需求:最近公司需要做一個樓宇對講的功能:門口機(連接WIFI)撥號對室內機(對應的WIFI)的設備進行呼叫,室內機收到呼叫之後將對收到的數據進行UDP廣播的轉發,手機(連接對應的WIFI)收到視頻流之後,實時的展示視頻數據(手機可以接聽,掛斷,手機接聽之後,室內機不展示視頻,只是進行轉發。) 簡單點 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...