Классы данных в Котлине

Классы данных в Котлине

1. обзор

Язык Kotlin представляет концепцию классов данных, которые представляют простые классы, используемые в качестве контейнеров данных, и не содержат никакой дополнительной логики. Проще говоря, решение Kotlin позволяет нам избежать написания большого количества шаблонного кода.

В этой быстрой статье мы рассмотрим классы данных в Kotlin и сравним их с их аналогами в Java.

2. Установка Kotlin

Чтобы приступить к настройке проекта Kotlin, ознакомьтесь с нашим руководствомintroduction to the Kotlin Language.

3. Классы данных в Java

Если бы мы хотели создать записьMovie на Java, нам нужно было бы написать много шаблонного кода:

public class Movie {

    private String name;
    private String studio;
    private float rating;

    public Movie(String name, String studio, float rating) {
        this.name = name;
        this.studio = studio;
        this.rating = rating;
    }

    public String getName() {
        return name;
    }

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

    public String getStudio() {
        return studio;
    }

    public void setStudio(String studio) {
        this.studio = studio;
    }

    public float getRating() {
        return rating;
    }

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

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;

        result = prime * result + ((name == null) ? 0 : name.hashCode());
        result = prime * result + Float.floatToIntBits(rating);
        result = prime * result + ((studio == null) ? 0 : studio.hashCode());

        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;

        if (obj == null)
            return false;

        if (getClass() != obj.getClass())
            return false;

        Movie other = (Movie) obj;

        if (name == null) {
            if (other.name != null)
                return false;

        } else if (!name.equals(other.name))
            return false;

        if (Float.floatToIntBits(rating) != Float.floatToIntBits(other.rating))
            return false;

        if (studio == null) {
            if (other.studio != null)
                return false;

        } else if (!studio.equals(other.studio))
            return false;

        return true;
    }

    @Override
    public String toString() {
        return "Movie [name=" + name + ", studio=" + studio + ", rating=" + rating + "]";
    }
}

86 строк кода. Это много, чтобы хранить всего три поля в простом классе.

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

Теперь создадимthe same Movie class, with the same functionalities, using Kotlin:

data class Movie(var name: String, var studio: String, var rating: Float)

Как видим, это намного проще и чище. Конструктор,toString(), equals(), hashCode(), и дополнительные функцииcopy() иcomponentN() генерируются автоматически.

4.1. использование

Класс данных создается так же, как и другие классы:

val movie = Movie("Whiplash", "Sony Pictures", 8.5F)

Теперь доступны свойства и функции:

println(movie.name)   //Whiplash
println(movie.studio) //Sony Pictures
println(movie.rating) //8.5

movie.rating = 9F

println(movie.toString()) //Movie(name=Whiplash, studio=Sony Pictures, rating=9.0)

4.2. Функция копирования

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

val betterRating = movie.copy(rating = 9.5F)
println(betterRating.toString()) // Movie(name=Whiplash, studio=Sony Pictures, rating=9.5)

Java не предоставляет четкого, естественного способа копирования / клонирования объектов. Мы могли бы использовать интерфейсClonable,SerializationUtils.clone() илиcloning constructor.

4.3. Заявления о разрушении

Декларации разрушения позволяют нам рассматривать свойства объектов как отдельные значения. Для каждого свойства в классе данных out создаетсяcomponentN():

movie.component1() // name
movie.component2() // studio
movie.component3() // rating

Мы также можем создать несколько переменных из объекта или непосредственно из функции - важно помнить об использовании скобок:

val(name, studio, rating) = movie

fun getMovieInfo() = movie
val(namef, studiof, ratingf) = getMovieInfo()

4.4. Требования к классу данных

Чтобы создать класс данных, мы должны выполнить следующие требования:

  • Первичный конструктор должен иметь хотя бы один параметр

  • Все параметры первичного конструктора должны быть помечены какval илиvar.

  • Классы данных не могут быть абстрактными, открытыми, запечатанными или внутренними

  • (до 1.1.) Классы данных могут реализовывать только интерфейсы

Начиная с версии 1.1, классы данных могут расширять другие классы.

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

data class Movie(var name: String = "", var studio: String = "", var rating: Float = 0F)

5. Заключение

Мы видели классы данных в Kotlin, их использование и требования, уменьшенное количество написанного шаблонного кода и сравнения с тем же кодом на Java.

Если вы хотите узнать больше о Kotlin, просмотрите такие статьи, какKotlin Java Interoperability и уже упомянутыйIntroduction to the Kotlin Language.

Полную реализацию этих примеров можно найти в нашемGitHub project.