← Назад к вопросам
Как переопределить метод в классе-наследнике
1.6 Junior🔥 121 комментариев
#Kotlin основы#Архитектура и паттерны
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI26 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Переопределение методов в классе-наследнике (Override)
Переопределение (override) - это фундаментальная часть полиморфизма в ООП.
Основной синтаксис
open class Animal {
open fun makeSound() {
println("Generic animal sound")
}
}
class Dog : Animal() {
override fun makeSound() {
println("Woof!")
}
}
class Cat : Animal() {
override fun makeSound() {
println("Meow!")
}
}
// Использование
val dog: Animal = Dog()
val cat: Animal = Cat()
dog.makeSound() // Woof!
cat.makeSound() // Meow!
Правила переопределения
1. Класс должен быть open
open class Parent {
open fun method() {}
}
class Child : Parent() {
override fun method() {} // OK
}
2. Метод должен быть open
open class Parent {
fun regularMethod() {} // final (не переопределяется)
open fun virtualMethod() {} // можно переопределить
}
class Child : Parent() {
override fun virtualMethod() {} // OK
override fun regularMethod() {} // ОШИБКА!
}
Переопределение свойств
open class Vehicle {
open val speed: Int = 100
open fun drive() {
println("Driving at $speed km/h")
}
}
class Car : Vehicle() {
override val speed: Int = 200 // Переопределить свойство
override fun drive() {
println("Car driving at $speed km/h")
}
}
class Bike : Vehicle() {
override val speed: Int = 150
}
val car = Car()
car.drive() // Car driving at 200 km/h
Вызов метода родителя через super
open class Animal {
open fun makeSound() {
println("Generic sound")
}
}
class Dog : Animal() {
override fun makeSound() {
super.makeSound() // Вызвать метод родителя
println("Woof!") // Добавить свое поведение
}
}
// Output:
// Generic sound
// Woof!
Переопределение с разными сигнатурами
// ОШИБКА: сигнатура не совпадает
open class Parent {
open fun process(value: Int): String {
return "Processed: $value"
}
}
class Child : Parent() {
override fun process(value: Int): String { // Сигнатура совпадает
return "Child processed: $value"
}
// ОШИБКА: это не переопределение, а overload
fun process(value: String): String {
return "String: $value"
}
}
Переопределение в интерфейсах
interface Shape {
fun getArea(): Double
}
class Circle(val radius: Double) : Shape {
override fun getArea(): Double {
return Math.PI * radius * radius
}
}
class Rectangle(val width: Double, val height: Double) : Shape {
override fun getArea(): Double {
return width * height
}
}
Абстрактные классы
abstract class Animal {
abstract fun makeSound() // Must be overridden
fun sleep() {
println("Sleeping")
}
}
class Dog : Animal() {
override fun makeSound() {
println("Woof!")
}
// sleep() наследуется автоматически
}
// ОШИБКА: не переопределил abstract метод
class Bird : Animal() {
// Compile error: must override makeSound
}
Модификаторы доступа при переопределении
open class Parent {
open protected fun protectedMethod() {} // protected
open fun publicMethod() {} // public
}
class Child : Parent() {
override fun protectedMethod() {} // Может быть public
override public fun publicMethod() {} // Явно public
// ОШИБКА: нельзя сузить видимость
// override private fun publicMethod() {}
}
Переопределение с изменением типа возврата (Covariance)
open class Animal
class Dog : Animal()
open class AnimalFactory {
open fun create(): Animal {
return Animal()
}
}
class DogFactory : AnimalFactory() {
override fun create(): Dog { // Более специфичный тип
return Dog()
}
}
Практический пример: Lifecycle методы в Activity
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
override fun onStart() {
super.onStart()
// Инициализировать
}
override fun onPause() {
super.onPause()
// Сохранить состояние
}
override fun onDestroy() {
super.onDestroy()
// Очистить ресурсы
}
}
Проверка переопределения
open class Parent {
open fun method() {}
}
class Child : Parent() {
@Override // Аннотация (опциональна, но рекомендуется)
override fun method() {}
}
final переопределение
open class Parent {
open fun method1() {}
final override fun method2() {} // Больше не переопределяется
}
open class Child : Parent() {
override fun method1() {}
// ОШИБКА: method2 final
// override fun method2() {}
}
Когда использовать override
✅ Используй override для:
- Полиморфного поведения
- Lifecycle методов (onCreate, onStart и т.д.)
- Реализации интерфейсов
- Абстрактных методов
❌ Избегай:
- Нарушения Liskov Substitution Principle
- Значительного изменения контракта
- Превращения public в private
Вывод
Оверрайд - это механизм полиморфизма:
- Метод в родителе должен быть open
- Класс должен быть open
- Используй super для вызова родительского метода
- Сигнатура должна совпадать
- Переброс super.method() при необходимости