Подтвердить что ты не робот

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

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

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

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

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

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

4b9b3361

Ответ 1

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

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

function after_insert() {
  // Virtual
}

Какой базовый класс вызывается при возникновении события обновления/вставки.

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

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

Ответ 2

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

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

Ответ 3

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

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

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

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

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