Kotlin Smart Cast — это потрясающе!

Я не знал, что Kotlin может делать такое умное кастирование. Он достаточно умен, чтобы кастовать для вас автоматически, так что вам больше не нужно явно кастовать.

Эта статья была первоначально опубликована на vtsen.hashnode.dev 21 мая 2022 года.

Я совершенно упустил эту потрясающую возможность Kotlin в своем предыдущем посте — Полное сравнение синтаксиса C# и Kotlin.

Я узнал об этой умной функции только после 8 месяцев разработки Kotlin, и, возможно, я использовал ее, не зная об этом. IDE Android Studio позаботилась об этом!

Допустим, у вас есть BaseClass и ChildClass вот так.

open class BaseClass
class ChildClass(val value: Int): BaseClass()
Вход в полноэкранный режим Выйти из полноэкранного режима

и вы создаете объект ChildClass, на который ссылается BaseClass.

val obj: BaseClass = ChildClass(value = 7)
Вход в полноэкранный режим Выйти из полноэкранного режима

Чтобы получить доступ к данным в ChildClass, вы выполняете явное приведение ниже.

val childObj = obj as ChildClass
childObj.value
Войти в полноэкранный режим Выйти из полноэкранного режима

Однако компилятор Kotlin может автоматически выполнить умное приведение в следующем сценарии:

Пример 1

fun smartCastExample1() {
    val obj: BaseClass = ChildClass(value = 7)
    //Calling obj.value here is not allowed
    //because obj belongs to BaseClass

    if (obj is ChildClass) {
        //obj in this scope is smart cast to ChildClass.
        //Thus, accessing the obj.value is allowed here
        println("Child value is ${obj.value}")

        //You don't need to explicit cast like this
        val childObj = obj as ChildClass
        println("Child value is ${childObj.value}")
    }
}

Вход в полноэкранный режим Выход из полноэкранного режима

obj в этой области видимости if должен быть ChildClass, поэтому компилятор Kotlin выполняет умное приведение.

Пример 2

fun smartCastExample2() {
    val obj: BaseClass = ChildClass(value = 7)
    if (obj !is ChildClass) return

    // obj is smart cast to ChildClass
    println("Child value is ${obj.value}")
}
Вход в полноэкранный режим Выход из полноэкранного режима

obj здесь должен быть ChildClass, так как он был возвращен, если это не так.

Пример 3

fun smartCastExample3() {
    val obj: BaseClass = ChildClass(value = 7)

    // obj at right side of || is smart cast to ChildClass
    if (obj !is ChildClass || obj.value == 7) return

}
Вход в полноэкранный режим Выход из полноэкранного режима

Это obj.value оценивается только тогда, когда obj является ChildClass. Если вы измените obj !is ChildClass на obj is ChildClass, умное приведение не будет работать.

Пример 4

fun smartCastExample3() {
    val obj: BaseClass = ChildClass(value = 7)

    // obj at right side of && is smart cast to ChildClass
    if (obj is ChildClass && obj.value == 7) return
}
Вход в полноэкранный режим Выход из полноэкранного режима

Аналогично примеру выше, вторая проверка выполняется только тогда, когда obj является ChildClass. Если вы измените obj is ChildClass на obj !is ChildClass, умное приведение не будет работать.

Приведенный здесь пример — это приведение от супертипа к подтипу. Это также работает для нулевого типа к не нулевому. Другие примеры смотрите здесь.


См. также

  • Советы и рекомендации по Kotlin

Оцените статью
devanswers.ru
Добавить комментарий