Spec-Zone.ru › Kotlin 1.9

Отладка

В этом разделе рассматриваются аспекты отладки.

Всегда предоставляйте метод toString()

Для упрощения отладки добавьте реализацию метода toString() в каждый создаваемый класс, даже во внутренние. Если toString() является частью контракта, документально подтвердите это.

Следующий код — упрощенный пример из области графического моделирования:

class Vector2D(val x: Int, val y: Int)

fun main() {
    val result = (1..20).map { Vector2D(it, it) }
    println(result)
}

Вывод этого кода не очень полезен:

[Vector2D@27bc2616, Vector2D@3941a79c, Vector2D@506e1b77,...]

Точно так же и информация в окне отладчика неинформативна:

Vector class objects in the debug tool window

Для повышения читабельности логов и отладки добавьте простую реализацию метода toString() следующим образом:

override fun toString(): String =
    "Vector2D(x=$x, y=$y)"

Это приводит к улучшенному выводу:

[Vector2D(x=1, y=1), Vector2D(x=2, y=2), Vector2D(x=3, y=3), ...
Improved output of vector class objects in the debug tool window

Может показаться хорошей идеей использовать классы данных, так как у них автоматически реализован метод toString(). В разделе Обратная совместимость этого руководства вы узнаете почему лучше этого не делать.

Рассмотрите реализацию метода toString() даже если не ожидаете вывода класса, так как это может помочь в непредвиденных ситуациях. Например, внутри строителей важно видеть текущее состояние строителя.

class Person(
    val name: String?,
    val age: Int?,
    val children: List<Person>
) {
    override fun toString(): String =
        "Person(name=$name, age=$age, children=$children)"
}

class PersonBuilder {
    var name: String? = null
    var age: Int? = null
    val children = arrayListOf<Person>()
    fun child(personBuilder: PersonBuilder.() -> Unit = {}) {
        children.add(person(personBuilder))
    }
}

fun person(personBuilder: PersonBuilder.() -> Unit = {}): Person {
    val builder = PersonBuilder()
    builder.personBuilder()
    return Person(builder.name, builder.age, builder.children)
}

Предполагаемое использование вышеприведенного кода таково:

Usage of the person DSL and a breakpoint

Если вы установите точку останова на строке после закрывающей фигурной скобки первого child (как на изображении выше), в выводе отладки вы увидите неинформативную строку:

Result of a PersonBuilder debugging

Если добавить простую реализацию toString() следующим образом:

override fun toString(): String =
    "PersonBuilder(name=$name, age=$age, children=$children)"

Данные отладки станут гораздо более понятными:

Result of a PersonBuilder improved debugging

Вы также сразу увидите, какие поля установлены, а какие — нет.

Будьте осторожны с экспонированием полей в toString() так как это может привести к StackOverflowException. Например, если children содержит ссылку на родительский элемент, это создаст циклическую ссылку. Также будьте осторожны с экспонированием списков и карт, так как toString() может расширить глубоко вложенную иерархию.

Что дальше?

Узнайте об обратной совместимости API.

Последнее изменение: 25 июля 2023 г.
Предсказуемость Обратная совместимость

© 2010–2023 JetBrains s.r.o. and Kotlin Programming Language contributors
Licensed under the Apache License, Version 2.0.
https://kotlinlang.org/docs/jvm-api-guidelines-debuggability.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API