Абстрактный класс — это класс, который не может быть инстанциирован напрямую и предназначен для наследования. Он может содержать как абстрактные (без реализации), так и конкретные методы.
Характеристики:
abstract class Animal(
protected val name: String // Абстрактный класс может иметь свойства
) {
// Абстрактный метод (без реализации)
abstract fun makeSound()
// Обычный метод с реализацией
fun eat() {
println("$name is eating")
}
}
class Dog(name: String) : Animal(name) {
override fun makeSound() {
println("$name says: Woof!")
}
}
Когда использовать:
Интерфейс — это контракт, который определяет, что класс должен делать, но не как он должен это делать. С Kotlin 1.4 интерфейсы могут иметь реализацию методов (default-методы).
Характеристики:
interface ClickListener {
fun onClick() // Абстрактный метод
// Метод с реализацией (default метод)
fun onLongClick() {
println("Default long click behavior")
}
}
class Button : ClickListener {
override fun onClick() {
println("Button clicked")
}
// onLongClick не обязательно переопределять
}
Когда использовать:
Характеристика | Абстрактный класс | Интерфейс |
---|---|---|
Инстанциирование | Нельзя создать экземпляр | Нельзя создать экземпляр |
Состояние | Может содержать поля | Может содержать свойства (но без backing field) |
Конструкторы | Может иметь конструкторы | Не может иметь конструкторов |
Множественное наследование | Нет (только один абстрактный класс) | Да (можно реализовать несколько интерфейсов) |
Модификаторы доступа | Может иметь protected члены | Все члены public (по умолчанию) |
Default-методы | Всегда мог иметь реализованные методы | С Kotlin 1.4 может иметь реализацию |
interface MainView {
fun showProgress()
fun hideProgress()
fun showData(data: List<Item>)
}
class MainActivity : AppCompatActivity(), MainView {
override fun showProgress() { /* ... */ }
// ...
}
abstract class BaseActivity : AppCompatActivity() {
abstract val layoutRes: Int
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(layoutRes)
setupViews()
}
protected open fun setupViews() {}
}
class MainActivity : BaseActivity() {
override val layoutRes: Int = R.layout.activity_main
override fun setupViews() {
// Инициализация UI
}
}
interface Repository<T> {
fun add(item: T)
fun get(id: String): T?
}
abstract class BaseRepository<T> : Repository<T> {
protected val items = mutableListOf<T>()
override fun add(item: T) {
items.add(item)
}
override fun get(id: String): T? {
return items.find { /* логика поиска */ }
}
}
interface Printer {
fun print() {
println("Printing...")
}
}
class Document : Printer {
// Можно не переопределять print()
}
interface Engine {
fun start()
}
class ElectricEngine : Engine {
override fun start() { println("Electric engine started") }
}
class Car(engine: Engine) : Engine by engine // Делегирование
абстрактные классы лучше использовать для создания иерархий родственных классов с общей базовой реализацией, тогда как интерфейсы подходят для определения контрактов, которые могут быть реализованы разными классами. В современной Android-разработке часто используют комбинацию обоих подходов для достижения гибкости и повторного использования кода.