Правильная реализация виртуальных функций в PHP?

на моем рабочем месте (только php) у нас есть базовый класс для абстракции базы данных. Если вы хотите добавить новую базовую таблицу базы данных на базовый уровень, вам необходимо создать подкласс этого базового класса и переопределить некоторые методы для определения индивидуального поведения для использования этой таблицы. Нормальное поведение должно оставаться неизменным.

Теперь я видел много новых программистов в нашей компании, которые просто переопределяют метод поведения по умолчанию. Некоторые из них настолько «хороши», чтобы использовать все поведение по умолчанию и просто добавлять туда отдельные вещи, где им это нравится, другие убивают самих себя, пытаясь использовать базовый класс и свой наследник.

Моя первая мысль решить эту проблему, думала об абстрактных методах, которые должны быть преодолены путем наследования классов. Но помимо других аргументов против абстрактных методов «абстрактное» просто не показывает, почему базовый класс нельзя использовать сам по себе и почему эта функция должна быть переопределена.

После некоторого поиска в Google я не нашел хорошего ответа на реализацию «реальных» виртуальных функций в php (просто есть виртуальная функция, которая почти убивает все надежды на конкретную реализацию).

Итак, что бы вы сделали с этим вопросом?

В PHP все общедоступные и защищенные функции являются «виртуальными». Вы можете предотвратить переопределение функций, добавив последнее ключевое слово. (Или, делая их частными, но это, вероятно, плохая идея).

В дизайне базового слоя я бы подумал о поведении, которое подклассы хотели бы затронуть. Я бы, например, создал пустые функции, такие как before_update () и after_insert ().

function after_insert() { // Virtual } 

Какой базовый класс вызовет, когда произойдет событие update / insert.

Может быть, функция is_valid (), которая всегда возвращает true в базовом классе и использует блок комментариев для описания последствий, когда подкласс возвращает false.

Надеюсь, это даст вам некоторое вдохновение.

Вы всегда можете использовать ключевое слово «final» для предотвращения переопределения некоторых функций классов, если люди используют этот класс не по назначению.

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

Без примера реализации вашего базового класса трудно дать конкретную информацию. Но на ум приходит кое-что:

  1. Абстракция базы данных – это сложный материал для начала. Я понимаю, что ты хочешь держать его скудным, чистым и скупым, но я думаю, что это довольно сложно. Вам действительно нужно внимательно изучить спецификации различных механизмов БД, чтобы увидеть, какие части являются общими, а какие части нуждаются в специализации. Также; вы уверены, что нет абстракции DB, смешанной с шаблоном Gateway Table Data, поскольку вы говорите о добавлении таблиц БД путем расширения базового класса?

  2. Методы вашего текущего базового класса могут делать слишком много и / или не являются достаточно общими для начала, если расширенные классы перегибаются назад, также сохраняют чистоту. Может быть, вы должны разбить методы интерфейса базового класса на более мелкие защищенные методы, которые достаточно общие, чтобы их можно было повторно использовать в переопределяющих методах расширенных классов? Или наоборот: возможно, у вас должны быть крючки для переопределяемых методов в ваших методах интерфейса.

  3. Как следует из пункта 2: что не так с абстрактным классом с некоторыми общепринятыми методами, и пусть ваш ванильный класс (ваш базовый класс) и другие классы наследуют от этого ?

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