Могу ли я указать строгие требования к методам для дочерних классов? - PullRequest
1 голос
/ 12 декабря 2008

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

Попробовав это абстрактным методом, php этого не допустит. Возможно ли это?

Ответы [ 4 ]

6 голосов
/ 12 декабря 2008

Функция дочернего класса может добавлять дополнительные, необязательные аргументы к сигнатуре, не вызывая ошибок:

abstract class Foo {
  abstract function bar($a);
}

class NewFoo extends Foo {

  function bar($a, $b = null) {
    //do something
  }
}
3 голосов
/ 12 декабря 2008

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

1 голос
/ 12 декабря 2008

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

Действительно возможно сделать то, о чем вы говорите, как своего рода хак, обоими способами, упомянутыми выше, с помощью:

func_get_args()

или просто (как упоминалось в комментариях) передайте массив аргументов. В качестве альтернативы вы можете передать объект, который имеет ваши аргументы в качестве членов данных. Затем вы можете расширить объект параметра / аргумента для вашего дочернего метода.

Дело в том, что PHP - это язык, который процветает благодаря вседозволенности, а не ограничениям . Абстрактные классы имеют очень простую реализацию в PHP. Если вам нужна такая структура, то PHP может оказаться не лучшим выбором для языка.

0 голосов
/ 12 декабря 2008

Я не думаю, что это ответ, который вы захотите использовать в производстве, поскольку он будет довольно медленным, но просто ради этого я попытался написать что-то, используя 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();
...