Kotlin Data類


資料類是一個簡單的類,用於儲存資料/狀態並包含標準功能(函式)。 data關鍵字用於將類宣告為資料類。

data class User(val name: String, val age: Int)

宣告資料類必須至少包含一個帶有屬性引數(valvar)的主建構函式。

資料類內部有以下函式:

  • equals(): Boolean
  • hashCode(): Int
  • toString(): String
  • component() 函式對應的屬性
  • copy()

由於資料類內部存在上述函式,因此資料類消除了反復套用程式碼。

*Java資料類和Kotlin資料類的比較

如果想使用資料類在Java中建立使用者資料項,則需要大量反復套用的程式碼。

import java.util.Objects;

public class User {
    private String name;
    private int id;
    private String email;

    public User(String name, int id, String email) {
        this.name = name;
        this.id = id;
        this.email = email;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public intgetId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof User)) return false;
        User user = (User) o;
        return getId() == user.getId() &&
                Objects.equals(getName(), user.getName()) &&
                Objects.equals(getEmail(), user.getEmail());
    }

    @Override
    public inthashCode() {

        return Objects.hash(getName(), getId(), getEmail());
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", id=" + id +
                ", email='" + email + '\'' +
                '}';
    }
}

使用User類的物件,呼叫上述Java資料類別建構函式,如下所示 -

class MyClass{
    public static void main(String agrs[]){
        User u = new User("Susen",10010,"[email protected]");
        System.out.println(u);
    }
}

執行上面範例程式碼,得到以下結果 -

User{name='Susen', id=10010, email='[email protected]'}

上述Java資料類程式碼在Kotlin資料程式碼中使用一行重寫完事 -

data class User(var name: String, var id: Int, var email: String)

使用User類的物件呼叫上述Kotlin資料類別建構函式 -

data class User(var name: String, var id: Int, var email: String)

fun main(agrs: Array<String>) {
    val u = User("Maxsu", 10010, "[email protected]")
    println(u)
}

執行上面範例程式碼,得到以下結果 -

User{name='Maxsu', id=10010, email='[email protected]'}

資料類的要求

要建立資料類,首先需要滿足以下要求:

  • 包含具有至少一個引數的主建構函式。
  • 主建構函式的引數標記為valvar
  • 資料類不能是抽象的,內部的,開放的或密封的。
  • 1.1版本之前,資料類只實現介面。1.1版本之後,資料類可以擴充套件其他類。

Kotlin資料類toString()方法

Kotlin資料類僅關注資料而非程式碼實現。
下面來看一個沒有資料類的簡單程式。 在這個類中,嘗試使用物件列印Product類的參照。

class Product(varitem: String, var price: Int)

fun main(agrs: Array<String>) {
    val p = Product("Thinkpad", 5600)
    println(p)
}

在列印Product類的參照時,它會顯示類名為ProducthashCode()。它不列印物件屬性的資料。

執行上面範例程式碼,得到以下結果 -

Product@5e2de80c

上述程式使用資料類(data class)重寫,列印Product類的參照並顯示物件的資料。上面程式碼中之所以發生這種情況,是因為資料類內部包含toString()方法,它預設只是顯示物件的字串表示形式。

data class Product(var item: String, var price: Int)

fun main(agrs: Array<String>) {
    val p = Product("Thinkpad", 5600)
    println(p)
}

執行上面範例程式碼,得到以下結果 -

Product(item=Thinkpad, price=5600)

Kotlin資料類equals()和 hashCode()方法

equal()方法用於檢查其他物件是否「等於」當前物件。 在兩個或多個hashCode()之間進行比較時,如果hashCode()相等,則equals()方法返回true,否則返回false

例如,讓我們看一個例子,一個普通類比較具有相同資料的Product類的兩個參照。

class Product(var item: String, var price: Int)

fun main(agrs: Array<String>) {
    val p1 = Product("Thinkpad", 5000)
    val p2 = Product("Thinkpad", 5000)
    println(p1==p2)
    println(p1.equals(p2))
}

在上述程式中,參照p1和參照p2具有不同的參照。 由於p1p2中的參照值不同,所以進行比較結果為false

執行上面範例程式碼,得到以下結果 -

false
false

上述程式使用資料類重寫,列印Product類的參照並顯示物件的資料。
hashCode()方法返回物件的雜湊碼。 如果兩個物件相等,則hashCode()會產生相同的整數結果。

data class Product(var item: String, var price: Int)

fun main(agrs: Array<String>) {
    val p1 = Product("Thinkpad", 5000)
    val p2 = Product("Thinkpad", 5000)
    println(p1==p2)
    println(p1.equals(p2))
}

執行上面範例程式碼,得到以下結果 -

true
true

Kotlin資料類copy()方法

資料類提供了一個copy()方法,用於建立物件的副本(或冒號)。 使用copy()方法,可以更改物件的部分或全部屬性。

範例:

data class Product(var item: String, var price: Int)

fun main(agrs: Array<String>) {
    val p1 = Product("Thinkpad", 5000)
    println("p1 包含資料為: $p1")
    val p2 = p1.copy()
    println("p2 拷貝物件包含p1的預設資料為:: $p2")
    val p3 = p1.copy(price = 20000)
    println("p3 包含 p1 和修改後的資料為 : $p3")
}

執行上面範例程式碼,得到以下結果 -

p1 包含資料為: Product(item=Thinkpad, price=5000)
p2 拷貝物件包含p1的預設資料為:: Product(item=Thinkpad, price=5000)
p3 包含 p1 和修改後的資料為 : Product(item=Thinkpad, price=20000)

資料類的預設和命名引數

還可以在資料類的主建構函式中分配預設引數。 如果需要,可以稍後在程式中更改這些預設值。

範例:

data class Product(var item: String = "Apple Mac", var price: Int = 15000)

fun main(agrs: Array<String>) {
    val p1 = Product(price = 20000)
    println(p1)
}

執行上面範例程式碼,得到以下結果 -

Product(item=Apple Mac, price=20000)