轉向Kotlin——資料類和封閉類

Android機動車發表於2018-05-04

資料類和封閉類是Kotlin中的兩種特殊的類,今天一起了解一下。更多精彩內容也可以關注我的微信公眾號——Android機動車

資料類

資料類是Kotlin的一個語法糖。Kotlin編譯器會自動為資料類生成一些成員函式,以提高開發效率。

資料類的使用

無論是Java伺服器開發還是Android開發,實體類自然是特別熟悉,它就是將Json格式轉化為一個只包含資料和基本操作方法的實體類,以方便網路存取和資料庫存取。

我們總是需要一個類來表示資料,例如要表示一個使用者的資料,我們會建立一個User類,並通過構造器傳入兩個屬性:

class User(name: String, age: Int) {
    var mName = name
    var mAge: Int = age
}
複製程式碼

我們定義實體類,除了要儲存資料之外,還需要輸出物件的值,比較物件等操作,前者會用到toString函式,後者會用到equals函式,如下:

var user1 = User("js", 20)
var user2 = User("lx", 12)

println(user1)
println(user2)
println(user1.equals(user2))
複製程式碼

輸出結果是:

User@3764951d
User@4b1210ee
false
複製程式碼

從結果可以看出,輸出User的兩個物件時,呼叫了這兩個物件的toString方法,但toString函式預設會呼叫hashcode函式,輸出當前物件的hashcode,並在前面加上 類名@

物件的equals方法預設也是比較了兩個物件的hashcode,兩個物件hashcode不同,自然返回false。

有時我們的業務需求是這樣的:列印物件,即按規則列印物件的所有屬性,兩個物件的所有屬性值相同,則返回兩個物件相等,於是乎我們需要重寫toString函式和equals函式,相信大家都會寫,這裡就不再累贅了。

儘管前面寫的User類實現了我們的需求,但會不會也太麻煩了,每個類都需要重寫toString和equals等方法。為了提高開發效率,Kotlin加入了我們馬上要介紹的資料類。

所謂資料類,就是隻定義必要的部分,其餘部分可以自動生成。

從上面的類可以看出,只有name和age是必須的,其餘的都是可以自動推導的。**資料類規定:屬性要通過主構造器指定,而且還要在class關鍵字之前加data。**我們再寫一個資料類,如下:

data class Person(var name: String, val age: Int)
複製程式碼

可以看出,原本十幾行幾十行的程式碼,現在一行就搞定了,其餘的Kotlin編譯器會自動生成。

資料類也和普通類一樣,也可以繼承其他類,有一些其他的成員函式等。

編寫一個資料類需要注意:

  • 主構造器至少要有一個引數;
  • 主構造器的引數要用var或val修飾;
  • 資料類不能是抽象類、open類、封閉類或者內部類。

由於主構造器中必須至少要有一個引數,所以在資料類中,不可能存在無參的主構造器,要想讓資料類擁有一個無參的構造器,有以下兩種方法:

  1. 為主構造器的每一個引數都加上預設值;
  2. 新增一個沒有引數的次構造器,並呼叫主構造器同時指定各引數。
data class MPerson(var name: String = "js", var age: Int = 20)

data class NPerson(var name: String, var age: Int) {
    // 次構造器,this呼叫主構造器,並指定引數
    constructor() : this("js", 20)
}
複製程式碼

物件的複製

在開發中,我們經常需要複製一個物件,然後修改它的一部分屬性,這就需要複製機制,Kotlin除了為資料類自動生成toString方法和equals方法,還預設生成了一個copy方法,它的作用就是複製資料類的例項。程式碼如下:

var person = Person("wj", 20)
var mCopyPerson1 = person.copy()
var mCopyPerson2 = person.copy(name = "js")
複製程式碼

資料類成員的解構

所謂解構,就是解除結構,指的是將資料物件中的屬性提取出來,分別賦給單個變數。

Kotlin編譯器會自動為資料類生成元件函式(以後會說到),因此,可以直接將資料類成員解構:

var js = Person("Js", 20)
// 將js.name和js.age分別賦給name和age變數
var (name, age) = js
println("$name, is $age years old")
複製程式碼

封閉類

封閉類可以看作是列舉的擴充套件。一個封閉類,前面用sealed關鍵字標識。可以有任意多個子類和物件。封閉類的值只能是這些子類和物件。

使用封閉類的好處是when表示式,不需要再使用else形式了。看個例子:

sealed class Expr

data class Const(var count: Int) : Expr()
data class Sun(var e1: Expr, var e2: Expr) : Expr()

fun evel(expr: Expr): Int = when (expr) {
    is Const -> expr.count
    is Sun -> evel(expr.e1) + evel(expr.e2)
}
複製程式碼

總結

在Kotlin中提供了一些特殊的類,其中資料類和封閉類就是其中的兩個。儘管這些特殊的類並不是必須的,但有些時候使用它們會給我們的開發帶來很大的方便,尤其是資料類。

更多精彩內容,歡迎關注我的微信公眾號——Android機動車

這裡寫圖片描述

相關文章