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)