Подтвердить что ты не робот

Kotlin: зачем использовать абстрактные классы (vs. интерфейсы)?

Я знаю о двух различиях между абстрактными классами и интерфейсами в Котлине:

  • Абстрактный класс может иметь состояние (например, var...)
  • Класс может реализовывать несколько интерфейсов, но не несколько абстрактных классов.

Поскольку Котлин - довольно свежий язык, мне интересно, почему абстрактные классы не были оставлены? Интерфейсы кажутся превосходным инструментом, с очень малой потребностью в абстрактных классах.

Чтобы уточнить: Kotlin поддерживает реализацию конкретных функций в интерфейсах, например:

interface Shiny {

    fun shine(amount : Int)  // abstract function

    fun reflect(s : String) { print ("**$s**") }  // concrete function

}

Может ли кто-нибудь дать сильный практический пример необходимости абстрактных классов?

4b9b3361

Ответ 1

Практическая сторона абстрактных классов заключается в том, что вы можете инкапсулировать часть реализации, которая работает с состоянием, так что она не может быть переопределена в производных классах.

В интерфейсе вы можете определить свойство без поля поддержки, а класс реализации должен переопределить это свойство (либо с помощью поля поддержки, либо с помощью специальных аксессуаров).

Учитывая, что вы не можете определить логику, которая надежно хранит некоторое состояние в интерфейсе: класс реализации может неожиданно переопределить свойства.

Пример:

interface MyContainer {
    var size: Int

    fun add(item: MyItem) { 
        // ...
        size = size + 1
    }
}

Здесь мы предоставляем реализацию по умолчанию для add, которая увеличивает size. Но он может сломаться, если класс реализации определен следующим образом:

class MyContainerImpl : MyContainer {
    override val size: Int 
        get() = 0
        set(value) { println("Just ignoring the $value") }
}

Напротив, абстрактные классы поддерживают этот прецедент и позволяют вам предоставить некоторые гарантии и контракт для всех их реализаций: они могут определять некоторое состояние и его переходы, которые останутся неизменными в производном классе.

Кроме того, абстрактные классы могут иметь не публичные API (внутренние, защищенные) и конечные члены, тогда как интерфейсы не могут (у них могут быть только частные члены, которые могут использоваться в реализациях по умолчанию) и все их реализации по умолчанию может быть переопределено в классах.

Ответ 2

Абстрактные классы существуют, по существу, для иерархии классов. Например, если абстрактный родительский класс имел конкретную функцию, которая также была определена в дочернем классе, который расширяет родительский класс, тогда в некоторых случаях необходимо вызвать родительскую функцию. Когда вы используете интерфейс, это невозможно сделать из-за полностью абстрактной природы класса.