@Lobanov

Можно ли так у конструктора задавать параметры и не противоречит ли это принципу Барбары Лисков?

Всем привет.
Погружаюсь в ООП и возник вопрос по созданию дочернего класса.

Есть родительский класс
class Animal {
    public function __construct(
        public string $name,
        public int $health,
        public int $power,
        public bool $alive = true
    ) {
    }

    public function calcDamage() {
        return $this->power * (mt_rand(100, 300) / 200);
    }

    public function applyDamage(int $damage) {
        $this->health -= $damage;

        if($this->health <= 0) {
            $this->health = 0;
            $this->alive = false;
        }
    }
}


Я от него наследуюсь и создаю следующий класс
class Mouse extends Animal {
    private float $hiddenLevel;
    public function __construct(
        public string $name,
        public int $health,
        public int $power
    ) {
        parent::__construct(name: $name, health: $health, power: $power);
        $this->hiddenLevel = 0.4;
    }
}


И вот тут у меня вопрос на счет конструкторов родителя и дочернего класса. Принцип Барбары Лисков гласит, что родитель может быть замещен ребенком без потери работоспособности кода (надеюсь я правильно понял этот принцип). И как я понимаю, конструктор ребенка должен совпадать с конструктором родителя.

Используя новшества PHP8 решил в конструкторе сразу же сделать присвоение параметров и последний параметр у меня необязательный. И тут у меня вопрос, надо ли согласно принципу Лисков передавать этот необязательный параметр дочернему классу ?

Хотел бы увидеть развернутые ответы от профи, чтобы получше разобраться в этом вопросе и огромная просьба, без флуда и каких-то споров в комментах.

Заранее благодарю.

P.S. Абстрактные классы и интерфейсы сейчас не рассматриваю, т.к. пытаюсь лучше разобраться в таких маленьких нюансах.
  • Вопрос задан
  • 147 просмотров
Решения вопроса 1
Adamos
@Adamos
LSP относится не к классам, а к объектам. Что у дочернего класса "под капотом", как он создается и действует вне реализации методов и свойств базового класса - это его личное дело.

С одной стороны, конструктор - часть интерфейса класса. С другой - никакой внешний код не сможет вызвать конструктор дочернего класса, ничего о нем не зная. А принцип применяется именно для того, чтобы внешний код мог ничего не знать о дочерних классах. Так что соблюдать LSP в конструкторе - просто бессмысленно.
Ответ написан
Пригласить эксперта
Ответы на вопрос 2
GavriKos
@GavriKos
Любые принципы вот эти - они абстрагированы от языка. Язык сверху накладывает на них ограничения. Поэтому 100% следования принципам не получается в общем смысле.

Поэтому мне кажется, вы сильно дословно восприняли рекомендации. Этот принцип не означает что можно взять и просто заменой (текстовой) поменять родителя на ребенка и все соберется без ошибок.
Это означает что ЛОГИЧЕСКИ можно заменить один класс на другой и ЛОГИЧЕСКИ ничего не сломается (а не будет ошибка компилятора)

И конкретно в вашем случае этот принцип не выполнится. Потому что если будет где то создание мертвого животного - на мышь вы его просто так не замените - логика отвалится.
Ответ написан
alestro
@alestro
Смысл в том, что бы не поломалось поведение в потомке.
class Mouse extends Animal {
    public function calcDamage() {
        throw new Exception('Мышь не наносит урон');
    }
}
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы