Класс данных Kotlin

В этом учебном пособии мы рассмотрим класс данных Kotlin. Если вы еще не читали сообщение Классы Kotlin, мы рекомендуем вам сделать это перед продолжением.

Класс данных Kotlin

Устали писать тысячи строк кода для ваших POJO-классов данных на Java? Каждый программист на Java на каком-то этапе должен был обратить внимание на количество строк кода, которые им нужно написать для классов, которые просто хранят некоторые данные. Давайте посмотрим, как выглядит POJO-класс Book.java:

public class Book {

    private String name;
    private String authorName;
    private long lastModifiedTimeStamp;
    private float rating;
    private int downloads;


    public Book(String name, String authorName, long lastModified, float rating, int downloads) {
        this.name = name;
        this.authorName = authorName;
        this.lastModifiedTimeStamp = lastModified;
        this.rating = rating;
        this.downloads = downloads;
    }

    public String getName() {
        return name;
    }

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

    public String getAuthorName() {
        return authorName;
    }

    public void setAuthorName(String authorName) {
        this.authorName = authorName;
    }

    public long getLastModifiedTimeStamp() {
        return lastModifiedTimeStamp;
    }

    public void setLastModifiedTimeStamp(long lastModifiedTimeStamp) {
        this.lastModifiedTimeStamp = lastModifiedTimeStamp;
    }

    public float getRating() {
        return rating;
    }

    public void setRating(float rating) {
        this.rating = rating;
    }

    public int getDownloads() {
        return downloads;
    }

    public void setDownloads(int downloads) {
        this.downloads = downloads;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        Book that = (Book) o;

        if (downloads != that.downloads)
            return false;
        if (name != null ? !name.equals(that.name) :
                that.name != null) {
            return false;
        }
        return authorName != null ?
                authorName.equals(that.authorName) :
                that.authorName == null;

    }

    @Override
    public int hashCode() {
        int result = name != null ? name.hashCode() : 0;
        result = 31 * result + (authorName != null ?
                authorName.hashCode() : 0);
        result = 31 * result + downloads;
        return result;
    }

    @Override
    public String toString() {
        return "Book{" +
                "name='" + name + '\'' +
                ", author='" + authorName + '\'' +
                ", lastModifiedTimestamp='" + lastModifiedTimeStamp + '\'' +
                ", rating='" + rating + '\'' +
                ", downloads=" + downloads +
                '}';
    }
}

ВАУ! Это 96 строк кода только для хранения 5 полей в объекте. Мы здесь не делаем ничего, кроме создания геттеров, сеттеров, методов toString(), equals() и hashCode(). С чистыми архитектурами и практиками разделения кода в наших проектах нам нужно создавать POJO-классы, так как каждый проект должен где-то хранить данные. Это может увеличить количество шаблонного кода. Вот где на помощь приходит Kotlin, с использованием классов данных. Классы данных – это ответ Kotlin на уменьшение шаблонного кода. Вышеприведенный POJO-класс можно написать на Kotlin следующим образом:

data class Book(var name: String, var authorName: String, var lastModified: Long, var rating: Float, var downloads: Int)

ВОТ И ВСЕ. Kotlin превращает 96-строчный код Java в одну строку кода. Это способ Kotlin уменьшить шаблонный код в вашем проекте!

Создание класса данных Kotlin

Ниже приведены требования для создания класса данных Kotlin.

  • Вы должны добавить ключевое слово data к классу
  • Первичный конструктор должен иметь как минимум один параметр.
  • Каждый параметр первичного конструктора должен иметь присвоенное значение val или var. В отличие от обычного класса, где указание val или var необязательно.
  • Классы данных не могут быть абстрактными, открытыми, запечатанными или внутренними

Встроенные методы класса данных Kotlin

Класс данных Kotlin автоматически создает следующие функции для вас.

  • equals() и hashCode()
  • toString() в форме "Book(name=JournalDev, authorName=Anupam)"
  • Функции componentN() для каждого из параметров в указанном порядке. Это известно как деструктивное объявление.
  • copy()

Особенности класса данных Kotlin

Вот некоторые функции, которые предоставляет класс данных.

  • Для создания конструктора без параметров укажите значения по умолчанию для каждого параметра, присутствующего в основном конструкторе.

  • Класс данных позволяет наследование (не нужно указывать ключевое слово open).

  • Вы можете предоставить явные реализации для функций equals(), hashCode() и toString()

  • Явные реализации функций copy() и componentN() не разрешены.

  • Мы можем контролировать видимость геттеров и сеттеров, указав модификаторы видимости в конструкторе, как показано ниже.

    data class Book(var name: String,private var authorName: String, var lastModified: Long, var rating: Float, var downloads: Int)
    
  • Параметр val не будет иметь неявно определенного сеттера (и не может быть явно определен!).

Аргументы по умолчанию и именованные аргументы в классе данных

Вот наш класс данных:

data class Book(var name: String, var authorName: String, var lastModified: Long, var rating: Float, var downloads: Int)

Для ни одного из параметров не установлено значение по умолчанию. Поэтому нам нужно установить аргумент для каждого из них при создании экземпляра, как показано ниже.

fun main(args: Array<String>) {
val book = Book("Android Tutorials","Anupam", 1234567, 4.5f, 1000)
}

Давайте установим несколько аргументов по умолчанию и посмотрим, как изменится создание экземпляра.


data class Book(var name: String, var authorName: String = "Anupam", var lastModified: Long = 1234567, var rating: Float = 5f, var downloads: Int = 1000)
fun main(args: Array<String>) {
var book = Book("Android tutorials","Anupam", 1234567, 4.5f, 1000)

    book = Book("Kotlin")
    book = Book("Swift",downloads = 500)
    book = Book("Java","Pankaj",rating = 5f, downloads = 1000)
    book = Book("Python","Shubham",rating = 5f)

}

Вместо того, чтобы устанавливать каждый аргумент, мы можем установить только те, которые отличаются от значения по умолчанию, а также те, которые мы хотим, используя именованные аргументы. Используя именованные аргументы, мы можем установить 5-й аргумент как второй, явно указав имя параметра, за которым следует =. Жизнь становится намного проще таким образом!

Метод toString() класса данных Kotlin

Метод toString() создается неявно и выводит имена и метки аргументов для экземпляра, как показано ниже.

data class Book(var name: String, var authorName: String = "Anupam", var lastModified: Long = 1234567, var rating: Float = 5f, var downloads: Int = 1000)


fun main(args: Array) {

    var book = Book("Android tutorials","Anupam", 1234567, 4.5f, 1000)
    println(book)
    book = Book("Kotlin")
    println(book)
    book = Book("Swift",downloads = 500)
    println(book)
    book = Book("Java","Pankaj",rating = 5f, downloads = 1000)
    println(book.toString())
    book = Book("Python","Shubham",rating = 5f)
    println(book.toString())


}

//Следующее выводится в консоли.
//Книга(название=Учебники по Android, имяАвтора=Анупам, последнееИзменение=1234567, рейтинг=4.5, загрузки=1000)
//Книга(название=Kotlin, имяАвтора=Анупам, последнееИзменение=1234567, рейтинг=5.0, загрузки=1000)
//Книга(название=Swift, имяАвтора=Анупам, последнееИзменение=1234567, рейтинг=5.0, загрузки=500)
//Книга(название=Java, имяАвтора=Панкадж, последнееИзменение=1234567, рейтинг=5.0, загрузки=1000)
//Книга(название=Python, имяАвтора=Шубхам, последнееИзменение=1234567, рейтинг=5.0, загрузки=1000)

Примечание: print функция неявно добавляет toString().

Метод копирования класса данных Kotlin

Функция копирования используется для создания копии экземпляра класса данных с изменением нескольких свойств. Рекомендуется использовать параметры val в конструкторе классов данных для использования неизменяемых свойств экземпляров. Неизменяемые объекты удобнее при работе с многопоточными приложениями. Следовательно, чтобы создать копию неизменяемого объекта, изменив только несколько свойств, удобна функция copy().

data class Book(val name: String, val authorName: String = "Anupam", val lastModified: Long = 1234567, val rating: Float = 5f, val downloads: Int = 1000)

fun main(args: Array) {

    val book = Book("Android tutorials","Anupam", 1234567, 4.5f, 1000)
    println(book)

    val newBook = book.copy(name = "Kotlin")
    println(newBook)
}
//Следующее выводится в консоли.
//Книга(название=Учебники по Android, имяАвтора=Анупам, последнееИзменение=1234567, рейтинг=4.5, загрузки=1000)
//Книга(название=Kotlin, имяАвтора=Анупам, последнееИзменение=1234567, рейтинг=4.5, загрузки=1000)

Класс данных Kotlin equals() и hashCode()

Метод hashCode() возвращает хэш-код для объекта. Если два объекта равны, hashCode() возвращает один и тот же целочисленный результат. Следовательно, equals() возвращает true, если hashCode() равен, иначе возвращает false.

data class Book(val name: String, val authorName: String = "Anupam", val lastModified: Long = 1234567, val rating: Float = 5f, val downloads: Int = 1000)

fun main(args: Array) {

    val book = Book("Android tutorials","Anupam", 1234567, 4.5f, 1000)
    println("Hashcode is ${book.hashCode()}")

    val newBook = book.copy(name = "Kotlin")
    println("Hashcode is ${newBook.hashCode()}")

    val copyBook = book.copy()
    println("Hashcode is ${copyBook.hashCode()}")


    if(copyBook.equals(book))
        println("copyBook and book are equal")

    if(!book.equals(newBook))
        println("newBook and book are NOT equal")

}

//Нижеприведенное отображается в консоли.
//Хэш-код равен 649213087
//Хэш-код равен 1237165820
//Хэш-код равен 649213087
//copyBook и book равны
//newBook и book НЕ равны

Первый и третий хэш-код объектов равны, следовательно, они равны. Note: Метод equals() эквивалентен == в Kotlin.

Декларации деструктуризации

Функция componentN() позволяет нам получить доступ к каждому из аргументов, указанных в конструкторе, в указанном порядке. N – количество параметров в конструкторе.

data class Book(val name: String, val authorName: String = "Anupam", val lastModified: Long = 1234567, val rating: Float = 5f, val downloads: Int = 1000)

fun main(args: Array<String>) {

    val book = Book("Android tutorials","Anupam", 1234567, 4.5f, 1000)

    println(book.component1()) //Android tutorials
    println(book.component2()) //Anupam
    println(book.component3()) //1234567
    println(book.component4()) //4.5
    println(book.component5()) //1000
    
}

Декларации деструктуризации позволяют нам получить доступ к аргументам как к свойствам из объекта класса, как показано ниже.

data class Book(val name: String, val authorName: String = "Anupam", val lastModified: Long = 1234567, val rating: Float = 5f, val downloads: Int = 1000)

fun main(args: Array<String>) {

    val book = Book("Android tutorials","Anupam", 1234567, 4.5f, 1000)
    val (n,a,date,rating,downloads) = book
}

Примечание: Если установлен модификатор видимости, такой как private, для любого из аргументов, он не может быть доступен в вышеуказанной функции.

data class Book(val name: String,private val authorName: String = "Anupam", val lastModified: Long = 1234567, val rating: Float = 5f, val downloads: Int = 1000)

fun main(args: Array<String>) {

    val book = Book("Android tutorials","Anupam", 1234567, 4.5f, 1000)
    val (n,a,date,rating,downloads) = book //This won't compile since authorName is private
}

Вот и все для быстрого обзора о Kotlin Data Classes. Ссылки: Kotlin Docs

Source:
https://www.digitalocean.com/community/tutorials/kotlin-data-class