Делегирование и наследование
Выбирайте композицию
«Делегирование и наследование» — бесплатный урок Kotlin Academy на CoddyKit. Это урок 3 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Kotlin Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Kotlin Academy содержит 4 уроков всего.
Два способа повторного использования
Наследование и делегирование позволяют повторно использовать поведение. Наследование означает, что класс является разновидностью другого класса. Делегирование означает, что класс содержит объект-сотрудник, которому он передаёт вызовы.
Классическая рекомендация: предпочитайте композицию наследованию.
Пример наследования
При наследовании подкласс расширяет базовый класс и переопределяет его члены. В языке Kotlin базовый класс должен быть open.
open class Animal {
open fun sound() = "..."
}
class Dog : Animal() {
override fun sound() = "woof"
}
fun main() {
println(Dog().sound())
}Пример делегирования
То же повторное использование с помощью делегирования: поведение находится в члене, которому класс переадресует вызовы.
interface Sound { fun sound(): String }
class Bark : Sound { override fun sound() = "woof" }
class Dog(s: Sound) : Sound by s
fun main() {
println(Dog(Bark()).sound())
}Хрупкий базовый класс
Наследование создаёт тесную связанность подкласса с внутренним устройством родительского класса. Изменение в базовом классе может незаметно нарушить работу подклассов — это проблема хрупкого базового класса. Делегирование зависит только от интерфейса.
Инкапсуляция
Подкласс может обращаться к защищённым членам и переопределять точки расширения, заглядывая во внутреннее устройство родительского класса. Делегирующий класс видит только публичный интерфейс и сохраняет инкапсуляцию.
interface Counter { fun increment(): Int }
class SimpleCounter : Counter {
private var n = 0
override fun increment(): Int { n++; return n }
}
class GuardedCounter(private val c: Counter) : Counter by c {
override fun increment(): Int {
println("incrementing")
return c.increment()
}
}
fun main() {
val g = GuardedCounter(SimpleCounter())
println(g.increment())
println(g.increment())
}Гибкость во время выполнения
Наследование фиксирует родительский класс во время компиляции. Делегирование позволяет подставлять разные реализации во время выполнения и упрощает тестирование с помощью подставных реализаций.
interface Clock { fun now(): Int }
class RealClock : Clock { override fun now() = 100 }
class FakeClock : Clock { override fun now() = 0 }
class Timer(c: Clock) : Clock by c
fun main() {
println(Timer(RealClock()).now())
println(Timer(FakeClock()).now()) // easy to test
}Несколько вариантов поведения
Класс может расширять только одного родителя, но делегировать работу множеству интерфейсов. Делегирование хорошо подходит для объединения нескольких возможностей.
interface Walk { fun walk() = "walking" }
interface Swim { fun swim() = "swimming" }
class Walker : Walk
class Swimmer : Swim
class Amphibian : Walk by Walker(), Swim by Swimmer()
fun main() {
val a = Amphibian()
println(a.walk() + ", " + a.swim())
}Когда подходит наследование
Наследование по-прежнему уместно для настоящего отношения is-a при наличии стабильной и спроектированной для расширения иерархии: семейств запечатанных типов, базовых классов фреймворка и полиморфизма на основе общего абстрактного типа.
sealed class Shape
class Circle(val r: Double) : Shape()
class Square(val s: Double) : Shape()
fun area(shape: Shape) = when (shape) {
is Circle -> 3.14 * shape.r * shape.r
is Square -> shape.s * shape.s
}
fun main() {
println(area(Circle(2.0)))
}Когда подходит делегирование
Выбирайте делегирование, если хотите:
- Повторно использовать поведение в несвязанных типах
- Объединять несколько возможностей
- Сохранять слабую связанность и упрощать тестирование
- Оборачивать и декорировать существующие реализации
Сравнение
Наследование: один родитель, тесная связанность, фиксация во время компиляции, is-a. Делегирование: множество взаимодействующих объектов, слабая связанность, возможность замены во время выполнения, has-a. Kotlin делает делегирование с помощью by почти бесплатным, склоняя выбор в пользу композиции.
Практическое правило по умолчанию
Хорошее правило: начинайте с делегирования. Переходите к наследованию только тогда, когда действительно появляется стабильная иерархия is-a. Это сохраняет гибкость проектирования и устойчивость к изменениям.
Быстрая проверка
Проверьте, насколько хорошо Вы понимаете разницу между делегированием и наследованием.
Итоги
Вы сравнили два подхода:
- Наследование: is-a, один родитель, тесная связанность
- Делегирование: has-a, множество взаимодействующих объектов, слабая связанность
- Предпочитайте композицию; используйте наследование для стабильных иерархий is-a
Далее: практические шаблоны декоратора с делегированием.
Часто задаваемые вопросы
Урок «Делегирование и наследование» бесплатный?
Да — полный текст урока «Делегирование и наследование» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Kotlin Academy, подпишись на CoddyKit PRO. Курс Kotlin Academy содержит 4 уроков всего.
Чему я научусь в уроке «Делегирование и наследование»?
Выбирайте композицию Ты практикуешь Kotlin Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать Kotlin Academy?
Предыдущий опыт не требуется. Kotlin Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 3 из 4.
Сколько времени занимает урок «Делегирование и наследование»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке Kotlin Academy?
Да. Каждый урок Kotlin Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Ключевое слово by
- Делегирование членам
- Делегирование и наследование
- Практические шаблоны