У меня есть базовый класс, в котором я хочу указать методы, которые должен иметь дочерний класс, но не реализовать их сам. Однако методы в дочернем классе могут иметь другое количество параметров, чем определение в базовом классе.
Попробовав это абстрактным методом, php этого не позволяет. Является ли это возможным?






Если не указать абстрактный метод без параметров и требовать от подкласса метода доступа к аргументам через func_get_args, я не понимаю, как это было бы возможно.
Я бы сказал, что это одна из слабых сторон объектной ориентации PHP, потому что она не предназначена для обработки такого рода сценариев использования. Это просто не предназначалось для того, чтобы разрешить перегруженные методы для
Действительно, можно сделать то, о чем вы говорите, как своего рода взлом, обоими способами, упомянутыми выше, с помощью:
func_get_args()
или просто (как упомянул комментатор) передать массив аргументов. В качестве альтернативы вы можете передать объект, у которого есть ваши аргументы как члены данных. Затем вы можете расширить объект параметра / аргумента для своего дочернего метода.
Дело в том, что PHP - это язык, который процветает на вседозволенности, а не на ограничениях. Абстрактные классы имеют очень простую реализацию в PHP. Если вам нужно много подобной структуры, то PHP действительно может быть не лучшим выбором языка.
Я не думаю, что это ответ, который вы захотите использовать в продакшене, поскольку он будет довольно медленным, но просто ради этого я попытался написать что-то с использованием Reflection, которое, похоже, работает. Вы все равно получите E_STRICT, потому что объявления методов в подклассах, по-видимому, должны совпадать.
class a {
protected $requiredMethodsInSubclass = array( 'method1', 'method2', 'method3' );
public function __construct() {
$reflObject = new ReflectionObject($this);
$className = $reflObject->getName();
if ($className == __CLASS__) {
//this class is being instanciated directly , so don't worry about any subclasses
return;
}
foreach ($this->requiredMethodsInSubclass as $methodName) {
try {
$reflMethod = $reflObject->getMethod($methodName);
} catch (ReflectionException $e) { //method not anywhere
trigger_error("Method $methodName is not declared in class " . __CLASS__ . " or subclass $className", E_USER_ERROR);
continue;
}
$declaringClass = $reflMethod->getDeclaringClass();
if ($declaringClass->getName() == __CLASS__) {
//method is declared in this class, not subclass
trigger_error("Method $methodName is not declared in subclass $className", E_USER_ERROR);
}
}
}
public function method1() {
}
public function method2($a) {
}
}
class b extends a {
public function __construct() {
parent::__construct();
//some stuff
}
public function method2($a, $b, $c) {
}
}
$b = new b();
Функция дочернего класса может добавлять дополнительные необязательные аргументы к подписи, не вызывая ошибок:
abstract class Foo {
abstract function bar($a);
}
class NewFoo extends Foo {
function bar($a, $b = null) {
//do something
}
}
Обратной стороной является использование только одного аргумента и требование передачи всех аргументов через массивы.