Один из вариантов использования встроенного класса.

Некоторое время назад, до того, как Kotlin представил встроенные классы, я создавал небольшой виджет, который должен был преобразовывать градусы Фаренгейта в градусы Цельсия и наоборот.

Поскольку оба они представлены как Double, я решил использовать псевдонимы типов для их разделения. Я подумал, что это крутая идея, поэтому я уволился и объявил свои псевдонимы типов и построил функции для их преобразования.

typealias Fahrenheit = Double
typealias Celsius = Double
fun convert(value: Fahrenheit): Celsius = TODO()
fun convert(value: Celsius): Fahrenheit = TODO()

Первая проблема, вы не можете этого сделать. Компилятор Kotlin не может отличить две подписи друг от друга. То же самое относится и к выражению when. Пока значение равно Double, оно всегда будет давать истину в выражении по Фаренгейту. Компилятор также скажет «Duplicate label in when» для псевдонимов двух типов.

return when(value) {
    is Fahrenheit -> TODO()
    is Celsius -> TODO()
}
// The above is actually resulting in this:
return when(value) {
    is Double -> TODO()
    is Double -> TODO()
}

Честно говоря, при следующей попытке расширение функционирует. И теперь семантика моей функции имеет особенность, которая радует компилятор.

fun Fahrenheit.toCelsius(): Celsius = TODO()
fun Celsius.toFahrenheit(): Fahrenheit = TODO()

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

val temperature: Fahrenheit = 0.0
val temperature2 = temperature.toFahrenheit()

Мы могли бы связывать «по Фаренгейту» или «по Цельсию» навсегда, не получая никаких ошибок кода, а только с ошибочными значениями.

Итак, в этот раз я сдался и отправил на Kotlin lang предложение исправить применяемые псевдонимы типов. И они думали, что это плохая идея для псевдонимов типов. Примерно через год была объявлена ​​функция встроенного класса, и я, наконец, смог написать идиоматический код, который хотел тогда. Вот как:

inline class Fahrenheit(val degree:Double)
inline class Celsius(val degree:Double)
fun convert(degree: Fahrenheit): Celsius = TODO()
fun convert(degree: Celsius): Fahrenheit = TODO()
fun Fahrenheit.toCelsius(): Celsius = TODO()
fun Celsius.toFahrenheit(): Fahrenheit = TODO()
val temperature = Fahrenheit(0.0)
val c = temperature.toCelsius() // can't call toFahrenheit here

А теперь будем надеяться, что скоро он выйдет из экспериментального. Https://kotlinlang.org/docs/reference/inline-classes.html#experimental-status-of-inline-classes

На данный момент существует несколько ограничений для встроенных классов. Но это уже другая история. Если вы хотите начать, вот официальная документация: https://kotlinlang.org/docs/reference/inline-classes.html

Спасибо за уделенное время!
→ Боб