Can I specify a custom method requirement for child classes?

I have a base class in which I want to specify the methods that the child class should have, but not implement them myself. However, methods in a child class can have a different number of parameters to be defined in the base class.

After trying this with an abstract method, php doesn't allow it. Is it possible?

+1


source to share


4 answers


Without specifying an abstract method with no parameters and requiring the subclass method to access args via func_get_args, I don't see how this is possible.



+3


source


The child class function can add additional optional arguments to the signature without throwing errors:



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

class NewFoo extends Foo {

  function bar($a, $b = null) {
    //do something
  }
}

      

+6


source


I would say that this is one of the weaknesses of PHP object orientation, that it is not designed to handle this kind of use case. It just wasn't meant for overloaded methods for

In fact, it is possible to do what you are talking about as a kind of hack, as mentioned above:

func_get_args()

      

or, just (like the commenter mentioned) pass an array of arguments. Alternatively, you can pass an object containing arguments as data items. Then you can extend the parameter / argument object for your child method.

The point is, PHP is a language that thrives on decidability, not constraint . Abstract classes have a very basic implementation in PHP. If you have a need for such a structure, then PHP is really not the best language choice.

+1


source


I don't think this is the answer you want to use in production as it will be quite slow, but just for the sake of it, I tried to write something using Reflection that seems to work. You will still get E_STRICT, because apparently the method descriptions in the subclasses should match.

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();

      

0


source







All Articles