Что такое наследование в ООП?

Ответ

Наследование — это механизм ООП, который позволяет создавать новый класс (дочерний, производный) на основе уже существующего класса (родительского, базового). Дочерний класс автоматически получает (наследует) все публичные и защищённые свойства и методы родительского класса, а также может:

  • Добавлять новые свойства и методы.
  • Переопределять унаследованные методы, изменяя их поведение.

Основная цель: повторное использование кода (DRY — Don't Repeat Yourself) и создание иерархии классов, отражающей логические отношения "является" (is-a).

Пример на PHP:

// Базовый (родительский) класс
class Vehicle {
    protected string $brand;

    public function __construct(string $brand) {
        $this->brand = $brand;
    }

    public function startEngine(): string {
        return "Двигатель транспортного средства {$this->brand} запущен.";
    }
}

// Дочерний класс. Car *является* Vehicle.
class Car extends Vehicle {
    private bool $isConvertible = false;

    // Переопределение метода родителя
    public function startEngine(): string {
        return "Автомобиль {$this->brand} завёлся с характерным рычанием!";
    }

    // Новый метод, специфичный для Car
    public function openRoof(): void {
        if ($this->isConvertible) {
            echo "Крыша открыта!";
        }
    }
}

// Другой дочерний класс
class Bicycle extends Vehicle {
    // Переопределение с вызовом родительской логики и дополнением
    public function startEngine(): string {
        // У велосипеда нет двигателя, поэтому базовое поведение не подходит.
        return "У велосипеда {$this->brand} нет двигателя. Крутите педали!";
    }
}

// Использование
$myCar = new Car('Toyota');
echo $myCar->startEngine(); // "Автомобиль Toyota завёлся с характерным рычанием!"

$myBike = new Bicycle('Stels');
echo $myBike->startEngine(); // "У велосипеда Stels нет двигателя. Крутите педали!"

Важные нюансы в PHP:

  • Поддерживается одиночное наследование (класс может наследовать только от одного родителя).
  • Для обращения к методу родительского класса из переопределённого метода используется ключевое слово parent:: (например, parent::startEngine()).
  • Модификатор доступа private в родительском классе означает, что свойство или метод не наследуются и не видны в дочернем классе.
  • Класс, объявленный как final, не может быть унаследован.

Ответ 18+ 🔞

Смотри, объясню тебе про наследование, как есть. Представь, что у тебя есть старый дедовский жигуль. Это, блядь, базовый класс. Он едет, тарахтит, бензин хавает как не в себя — но он едет. Так вот, наследование — это когда ты берешь этот жигуль, и делаешь из него, например, тачку с нитроускорителем и подсветкой салона. Новый класс получает всё от старого: и руль, и педали, и движок, который стучит. Но ты можешь добавить свою фишку — тот самый нитро, и можешь переопределить звук клаксона, чтобы он орал как полицейская сирена, а не пищал, как у велосипеда.

Смысл в чём? Чтобы не изобретать велосипед каждый раз, ёпта. Не писать один и тот же код для руля и педалей. Сказал «extends» — и всё, базовые плюшки твои. Это и есть DRY — не повторяйся, сука, а то заебешься.

Вот смотри на примере, тут всё понятно:

// Это наш старый дедовский жигуль. Базовый класс.
class Vehicle {
    protected string $brand; // Марка. protected — чтоб дети видели, а посторонние нет.

    public function __construct(string $brand) {
        $this->brand = $brand;
    }

    // Базовый метод — завестись.
    public function startEngine(): string {
        return "Двигатель транспортного средства {$this->brand} запущен.";
    }
}

// А вот наш прокачанный наследник. Car — это Vehicle, только круче.
class Car extends Vehicle {
    private bool $isConvertible = false; // Новая фишка, которой у деда не было.

    // Переопределили метод завода. Дед заводился скучно, а мы — с рыком!
    public function startEngine(): string {
        return "Автомобиль {$this->brand} завёлся с характерным рычанием!";
    }

    // А это наш уникальный метод. Только у кабриолета есть.
    public function openRoof(): void {
        if ($this->isConvertible) {
            echo "Крыша открыта!";
        }
    }
}

// А это другой наследник — велосипед. Он тоже транспорт, но, блядь, особенный.
class Bicycle extends Vehicle {
    // Тут мы вообще переопределяем всё. Какое нахуй зажигание?
    public function startEngine(): string {
        return "У велосипеда {$this->brand} нет двигателя. Крутите педали!";
    }
}

// Используем. Вот это мощь.
$myCar = new Car('Toyota');
echo $myCar->startEngine(); // Выведет: "Автомобиль Toyota завёлся с характерным рычанием!"
// Чувствуешь разницу? Не то что у деда.

$myBike = new Bicycle('Stels');
echo $myBike->startEngine(); // А тут: "У велосипеда Stels нет двигателя. Крутите педали!"
// Ну а чё, честно же, ебать колотить.

Важные фишки, чтобы не обосраться:

  • В PHP наследование одиночное. Это как с матерью — одну можешь выбрать, две нельзя. От одного класса наследуешься, и всё.
  • Хочешь в переопределённом методе всё же вызвать старый, дедовский? Используй parent::. Типа, parent::startEngine().
  • Если в базовом классе свойство или метод private — то это тайна, которую дети не увидят. Только protected и public переходят по наследству.
  • Бывает класс final — это как дед, который написал в завещании «хуй вам, а не наследники». От такого наследоваться нельзя, и всё тут.

Вот и вся магия. Создаёшь иерархию, повторно используешь код, не плодишь сущностей. Красота, ядрёна вошь!

Видео-ответы