Загрузка данных


// open class позволяет другим классам наследоваться от него (по умолчанию классы в Kotlin final)
open class Animal(val name: String) {
    // open метод можно переопределять (overide) в подклассах
    open fun makeSound(): String {
        return "$name издаёт звук"
    }
}

// Класс Dog наследуется от Animal через двоеточие `:`
class Dog(name: String) : Animal(name) {
    // переопределяем родительский метод
    override fun makeSound(): String {
        return "$name говорит: Гав-гав!"
    }

    // Уникальный метод только для собак
    fun fetch(): String {
        return "$name приносит палку"
    }
}

// Класс Cat тоже наследуется от Animal
class Cat(name: String) : Animal(name) {
    override fun makeSound(): String {
        return "$name говорит: Мяу!"
    }

    // Уникальный метод только для кошек
}
fun climb(): String {
    return "$name залез на шкаф"
}

fun main() {
    // Создаем список из 4 животных (компилятор сам понимает, что это List<Animal>)
    val animals = listOf(
        Dog("Шарик"),
        Cat("Мурка"),
        Dog("Бобик"),
        Cat("Барсик")
    )

    // Проходимся по списку
    for (animal in animals) {
        // Вызываем общий метод для всех животных
        println(animal.makeSound())

        // Smart Cast (умное приведение типов): 
        // Kotlin сам понимает тип объекта после проверки через `is`
        if (animal is Dog) {
            // Внутри этого блока `animal` автоматически становится типа `Dog`
            println(animal.fetch())
        } else if (animal is Cat) {
            // Внутри этого блока `animal` автоматически становится типа `Cat`
            println(animal.climb())
        }
    }
}