Псевдонимы типов

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

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

typealias NodeSet = Set<Network.Node>

typealias FileTable<K> = MutableMap<K, MutableList<File>>

Вы также можете объявить псевдонимы для функциональных типов:

typealias MyHandler = (Int, String, Any) -> Unit

typealias Predicate<T> = (T) -> Boolean

Вы можете ввести новые имена для внутренних или вложенных классов:

class A {
    inner class Inner
}
class B {
    inner class Inner
}

typealias AInner = A.Inner
typealias BInner = B.Inner

Псевдонимы типов не вводят новых типов. Они эквивалентны соответствующим базовым типам. Когда вы добавляете typealias Predicate<T> и используете Predicate<Int> в своём коде, компилятор Kotlin всегда преобразует это в (Int) -> Boolean. Таким образом, вы можете передать переменную своего типа туда, где требуется обычный функциональный тип, и наоборот:

typealias Predicate<T> = (T) -> Boolean

fun foo(p: Predicate<Int>) = p(42)

fun main() {
    val f: (Int) -> Boolean = { it > 0 }
    println(foo(f)) // выведет "true"

    val p: Predicate<Int> = { it > 0 }
    println(listOf(1, -2).filter(p)) // выведет "[1]"
}

Вложенные псевдонимы типов

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

class Dijkstra {
    typealias VisitedNodes = Set<Node>

    private fun step(visited: VisitedNodes, ...) = ...
}

Захват означает, что псевдоним типа ссылается на параметр типа, определённый во внешнем классе:

class Graph<Node> {
    // Некорректно, потому что захватывает Node
    typealias Path = List<Node>
}

Чтобы исправить эту проблему, объявите параметр типа непосредственно в псевдониме типа:

class Graph<Node> {
    // Корректно, потому что Node является параметром псевдонима типа
    typealias Path<Node> = List<Node>
}

Вложенные псевдонимы типов делают код чище и удобнее в сопровождении: они улучшают инкапсуляцию, уменьшают количество объявлений на уровне пакета и упрощают внутренние реализации.

Правила для вложенных псевдонимов типов

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

  • Вложенные псевдонимы типов должны соблюдать все существующие правила для псевдонимов типов.
  • С точки зрения видимости псевдоним не может открывать больше доступа, чем позволяют типы, на которые он ссылается.
  • Их область видимости такая же, как у вложенных классов. Их можно определять внутри классов, и они скрывают любые родительские псевдонимы типов с тем же именем, поскольку не переопределяют их.
  • Вложенные псевдонимы типов можно помечать как internal или private, чтобы ограничить их видимость.
  • Вложенные псевдонимы типов не поддерживаются в объявлениях expect/actual Kotlin Multiplatform.