paint-brush
Код запаха 286 - Метод родитель-ребенок перекрываетсяк@mcsee
Новая история

Код запаха 286 - Метод родитель-ребенок перекрывается

к Maximiliano Contieri4m2025/01/16
Read on Terminal Reader

Слишком долго; Читать

Коллизии частных методов в родительско-дочерних классах могут привести к ошибкам и запахам кода. Избегайте этого, поддерживая четкое именование, избегая перекрытий и следуя практикам чистого кода. Используйте методы в родительских классах с именами, которые могут использовать дочерние классы.
featured image - Код запаха 286 - Метод родитель-ребенок перекрывается
Maximiliano Contieri HackerNoon profile picture
0-item

Когда родительские и дочерние методы сталкиваются!


TL;DR: Избегайте использования закрытых методов в родительских классах с именами, которые могут использовать дочерние классы.

Проблемы

  • Нарушение принципа наименьшего удивления
  • Неожиданное поведение и дефекты
  • Скрытые зависимости
  • Ограниченная расширяемость
  • Неоднозначность кода
  • Нарушение принципа открытости/закрытости
  • Вводящий в заблуждение дизайн

Решения

  1. Избегайте иерархий
  2. Переименовать частные методы
  3. Поддерживайте четкое наименование
  4. Избегайте дублирования имен.
  5. Избегайте защищенных методов
  6. Подклассифицировать для основных отношений , не использовать код повторно

Контекст

Когда вы используете одно и то же имя метода в родительских и дочерних классах, вы создаете путаницу.

Закрытый метод в родительском классе не может быть переопределен, даже если в дочернем классе существует открытый метод с таким же именем.

Это проблема большинства статических языков, которые есть в их дизайне. Это разъединение приводит к ошибкам и затрудняет поддержку кода.

Образец кода

Неправильный

 <? class ParentClass { private function greet() { // This method is private return "Hello from ParentClass"; } public function callGreet() { return $this->greet(); } } class ChildClass extends ParentClass { public function greet() { // Overriding a concrete method is a code smell // Compilers SHOULD warn you return "Hello from ChildClass"; } } $child = new ChildClass(); echo $child->callGreet(); // When callGreet() is invoked on the $child object, // it executes the following: // It calls $this->greet(), // which refers to the greet() method of ParentClass // because the original method is private // and cannot be overridden or accessed from ChildClass. // The unexpected output is 'Hello from ParentClass'

Верно

 <? class ParentClass { protected function greet() { // notice the 'protected qualifier' return "Hello from ParentClass"; } public function callGreet() { return $this->greet(); } } class ChildClass extends ParentClass { public function greet() { return "Hello from ChildClass"; } } $child = new ChildClass(); echo $child->callGreet(); // The output is "Hello from ChildClass" // This is the standard (and wrong) solution // Also fixed by most AIs
 <? abstract class ParentClass { // Declare greet() as an abstract method // Following the template-method design pattern abstract protected function greet(); public function callGreet() { return $this->greet(); } } class ChildClass extends ParentClass { protected function greet() { return "Hello from ChildClass"; } } class OtherChild extends ParentClass { protected function greet() { return "Hello from OtherChild"; } } $child = new ChildClass(); echo $child->callGreet(); // Output: Hello from ChildClass $otherChild = new OtherChild(); echo $otherChild->callGreet(); // Output: Hello from OtherChild

Обнаружение

  • [x] Полуавтоматический

Вы можете обнаружить этот запах, посмотрев на частные методы в родительских классах и проверив, определяют ли дочерние классы методы с тем же именем. Вы также должны проверить родительские методы, вызывающие частные методы.

Теги

  • Иерархия

Уровень

  • [x] Средний

Почему важна биекция

Понятный и предсказуемый код должен отражать реальную иерархию, которую он моделирует.

При использовании закрытых методов с перекрывающимися именами создается разрыв биекции между моделью и реализацией.

Этот пробел сбивает с толку разработчиков, увеличивает количество дефектов и нарушает принципы чистого кода.

Генерация ИИ

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

Они могут не проверять уровни доступа или не учитывать последствия наследования.

Обнаружение ИИ

Инструменты ИИ могут устранить этот запах с помощью четких инструкций.

Вы можете попросить ИИ проверить наличие перекрывающихся имен методов и рефакторинг иерархий.


Попробуйте!

Помните: помощники на основе искусственного интеллекта совершают много ошибок

Без надлежащих инструкций

С конкретными инструкциями

ЧатGPT

ЧатGPT

Клод

Клод

Недоумение

Недоумение

Второй пилот

Второй пилот

Близнецы

Близнецы

Заключение

При проектировании родительских и дочерних классов следует использовать методы, которые четко определяют наследование и доступность.

Избегайте частных методов, которые перекрываются с дочерними методами. Это сохраняет ваш код читаемым, расширяемым и соответствующим принципам чистого кода.

Такие языки, как Python, позволяют переопределять родительские методы независимо от их имен, в то время как Java строго соблюдает уровни доступа.

C# ведет себя аналогично Java . Эти различия означают, что вам необходимо понимать конкретные правила языка, с которым вы работаете, чтобы избежать неожиданного поведения.

Отношения

https://hackernoon.com/how-to-find-the-stinky-parts-of-your-code-part-xxviii

https://hackernoon.com/how-to-find-the-stinky-parts-of-your-code-part-xii

https://hackernoon.com/how-to-find-the-stinky-parts-of-your-code-part-iii-t7h3zkv

https://hackernoon.com/how-to-find-the-stinky-parts-of-your-code-part-xxv

https://hackernoon.com/how-to-find-the-stinky-parts-of-your-code-part-viii-8mn3352


Отказ от ответственности: Code Smells — это мое мнение .

Авторы: Фото Мэтта Артца на Unsplash


Наследование — это хорошо, но никогда не следует забывать, что оно вносит тесную связь.

Роберт С. Мартин


Эта статья является частью серии CodeSmell на HackerNoon.