Когда определения типов отвлекают от значения вашего кода из-за нечитабельности, выразительности или просто длины, у Kotlin есть подходящая функция: typealias
! Typealias позволяет давать альтернативные имена типам классов или функций, не вводя при этом новых.
Для именования типа функции можно использовать псевдонимы типов:
typealias TeardownLogic = () -> Unit
fun onCancel(teardown : TeardownLogic){ }
private typealias OnDoggoClick = (dog: Pet.GoodDoggo) -> Unit
val onClick: OnDoggoClick
Недостатком этого является то, что имя скрывает параметры, передаваемые в функцию, что снижает ее читабельность:
typealias TeardownLogic = () -> Unit //or
typealias TeardownLogic = (exception: Exception) -> Unit
fun onCancel(teardown : TeardownLogic){
// Сложно увидеть какая информация нам
// доступна в TeardownLogic
}
Typealias
позволяет сократить длинные стандартные имена:
typealias Doggos = List<Pet.GoodDoggo>
fun train(dogs: Doggos){ … }
Но не торопитесь. Действительно ли использование псевдонима типа сделает код более осмысленным и читаемым?
Если вы работаете с длинным именем класса, можно использовать typealias
, чтобы сократить его:
Но здесь лучше всего было бы использовать псевдоним импорта:
import android.graphics.drawable.AnimatedVectorDrawable as AVDВ этом случае использование ярлыка на самом деле не помогает повысить читабельность, а IDE поможет автоматически заполнить имя класса.
Но импорт псевдонимов полезен тогда, когда вам нужно устранить неоднозначность между классами с одинаковым именем, поступающими из разных пакетов:
import io.plaidapp.R as appR
import io.plaidapp.about.R
Псевдонимы типов определяются вне классов, поэтому убедитесь, что вы учитываете их видимость при использовании.
typealias
в кроссплатформенных проектахПри работе с кроссплатформенными проектами в обычном коде можно указать интерфейсы, которые затем реализуются в коде платформы. Чтобы упростить это, Kotlin предоставляет механизм ожидаемых и фактических деклараций.
Интерфейсы в обычном коде — это ожидаемые объявления, определенные с помощью ключевого слова expect
. Реализация в коде платформы определяется с помощью ключевого слова actual
. Если реализация уже существует в одной из платформ и имеет все ожидаемые методы с точно такими же сигнатурами, то вы можете использовать typealias
для сопоставления имени класса с ожидаемым именем.
expect annotation class Test
actual typealias Test = org.junit.Test
Псевдонимы не создают новые типы. Например, декомпилированный код для функции train
будет просто использовать List:
// Kotlin
typealias Doggos = List<Pet.GoodDoggo>
fun train(dogs: Doggos) { … }
// Декомпилированный Java код
public static final void train(@NotNull List dogs) { … }
Вы не должны полагаться на псевдонимы типов для проверки их времени компиляции. Вместо этого следует рассмотреть возможность использования другого типа или встроенного класса. Например, предположим, что у нас есть следующая функция:
fun play(dogId: Long)Создание псевдонима типа Long
не поможет предотвратить ошибки при попытке передать неверный идентификатор:
typealias DogId = Long
fun pet(dogId: DogId) { … }
fun usage() {
val cat = Cat(1L)
pet(cat.catId) // компилируется
}
Псевдонимы типов — это способ предоставления более короткого или значимого имени для существующего типа. Если же коду необходима дополнительная безопасность, то лучше создать новый тип вместо использования псевдонимов.
Перевод статьи Florina Muntenescu: Alter type with typealias
Комментарии