Ответ
Наследование — это механизм ООП, который позволяет одному классу (дочернему, подклассу) наследовать свойства, методы и другие характеристики другого класса (родительского, суперкласса). Это основа для создания иерархий "is-a" (является).
Основные концепции в Swift:
- Базовый класс: Класс, не наследующий от других.
- Подкласс: Класс, который наследует от суперкласса. Может:
- Добавлять новые свойства и методы.
- Переопределять унаследованные методы, свойства, сабскрипты с помощью ключевого слова
override. - Обращаться к реализации суперкласса через
super.
- Одиночное наследование: Класс в Swift может наследовать только от одного суперкласса.
- Запрет наследования: Ключевое слово
finalпредотвращает дальнейшее наследование от класса или переопределение конкретного метода.
Пример:
// Суперкласс (базовый класс)
class Vehicle {
var currentSpeed: Double = 0.0
var description: String {
return "движется со скоростью (currentSpeed) км/ч"
}
func makeSound() {
// Универсальный звук, который будет переопределён
}
}
// Подкласс
class Bicycle: Vehicle {
var hasBasket = false
// Наследует currentSpeed и description
}
// Подкласс с переопределением
class Car: Vehicle {
var gear = 1
// Переопределение вычисляемого свойства
override var description: String {
return super.description + " на передаче (gear)"
}
// Переопределение метода
override func makeSound() {
print("Beep beep!")
}
}
let bike = Bicycle()
bike.currentSpeed = 15
print(bike.description) // "движется со скоростью 15.0 км/ч"
let car = Car()
car.currentSpeed = 60
car.gear = 3
print(car.description) // "движется со скоростью 60.0 км/ч на передаче 3"
car.makeSound() // "Beep beep!"
Альтернативы: Для большей гибкости и избежания хрупких иерархий часто предпочитают композицию (протоколы, dependency injection) вместо глубокого наследования.
Ответ 18+ 🔞
Давай разберём эту штуку про наследование, а то звучит как какая-то семейная драма с наследством, только для классов.
Смотри, представь себе, есть у тебя какой-нибудь базовый класс, типа Vehicle (транспорт). Ну, как бы общее понятие. У него есть какие-то свойства: currentSpeed, какая-то description. Он умеет makeSound() (хотя звук у абстрактного транспорта — это пиздец какой-то абстрактный свист в вакууме).
class Vehicle {
var currentSpeed: Double = 0.0
var description: String {
return "движется со скоростью (currentSpeed) км/ч"
}
func makeSound() {
// Тишина, блядь. Абстракция.
}
}
И вот появляется его сынок, подкласс Bicycle. Велосипед, ёпта. Он наследует ВСЁ от родителя. То есть у него автоматом появляются и currentSpeed, и description. Но он может ещё и своё добавить — корзинку, например. Он как бы говорит: «Я — транспорт (is-a), но ещё и с корзинкой».
class Bicycle: Vehicle {
var hasBasket = false // А вот и корзинка, мать его!
}
А теперь смотри сюда, самый сок — переопределение. Появляется класс Car. Машина — тоже транспорт. Но она не может просто «делать звук» как абстрактная хуйня. Ей надо «бип-бип» орать. И в описании хочется ещё передачу указать.
Так вот, чтобы сказать системе: «Отстань, родитель, я сам знаю, как это делать», используется слово override. Это как крик подростка «Я сам!», только для кода. А через super можно позвать родительскую реализацию, типа «ладно, пап, извини, но я всё равно сделаю по-своему».
class Car: Vehicle {
var gear = 1
// Переопределяем описание
override var description: String {
// Сперва берём то, что дал родитель...
return super.description + " на передаче (gear)"
}
// А тут полностью заменяем звук
override func makeSound() {
print("Beep beep!") // Вот так, блядь, а не тишина!
}
}
И вот что получается в итоге:
let bike = Bicycle()
bike.currentSpeed = 15
print(bike.description) // "движется со скоростью 15.0 км/ч" — всё от родителя
let car = Car()
car.currentSpeed = 60
car.gear = 3
print(car.description) // "движется со скоростью 60.0 км/ч на передаче 3" — родительское + своё
car.makeSound() // "Beep beep!" — своё, ебать!
Но есть нюанс, Карл! В Swift нельзя быть мультиинструменталом — один класс может наследоваться только от одного родителя. Многомужества нет, только одиночное наследование.
А если ты хочешь запретить кому-то быть родителем или переопределять твои методы — поставь перед классом или методом слово final. Это как табличка «Не влезай, убьёт!». Наследников не будет, иди нахуй.
И последнее, самое важное. Глубокие иерархии наследования — это иногда пиздец как сложно и хрупко. Как карточный домик, тронул одно — всё ебнулось. Поэтому умные дяди часто советуют вместо «является» (наследование) использовать «имеет» (композиция, протоколы). Это как вместо того, чтобы быть сыном знаменитого актёра и всю жизнь оправдывать ожидания, лучше просто взять у него денег в долг (протокол) и делать что хочешь. Гибче, блядь, и голова не болит.
Вот и вся магия. Не так страшен чёрт, как его малюют. Главное — не создавать монстров с десятью уровнями наследования, а то сам потом будешь плакать, пытаясь понять, откуда у объекта взялось свойство someShit.