1

I have an abstract class and child's:

abstract class Cubique_Helper_Abstract {
    abstract public function execute();
}

class Cubique_Helper_Doctype extends Cubique_Helper_Abstract{
    public function execute($type) {}
}

As you can see, method execute() is common. But number of arguments can be different in all classes. How can I keep this extending with different arguments of method?

It's my current error:

Declaration of Cubique_Helper_Doctype::execute() must be compatible
with that of Cubique_Helper_Abstract::execute()

Thank you i advance.

2
  • You could get the arguments with func_get_args instead of defining them in the signature. Or in the abstract class, you can define the method to accept one value, which is an (associative) array. In the child classes you just access the keys you need. Commented Sep 22, 2011 at 8:13
  • @stereofrog: I absolutely concur, +1. For my learning purposes, would you comment on my answer here below? Cheers Commented Sep 22, 2011 at 8:35

4 Answers 4

3

you can make method or function with out limited argument.

function test(){
$num = func_num_args();
for ($i = 0;$i < $num;$i++)
{
    $arg[$i] = func_get_arg($i); 
}
    // process on arguments  
}
Sign up to request clarification or add additional context in comments.

Comments

2
  • You could remove execute() from the abstract, but you probably do not want to do that.

  • You could also give it an data object as argument, like this:

    class MyOptions {
      public function getType(){}
      public function getStuff(){}
    }
    
    abstract class Cubique_Helper_Abstract {
        abstract public function execute(MyOptions $options);
    }
    
    class Cubique_Helper_Doctype extends Cubique_Helper_Abstract{
      public function execute(MyOptions $options) {
        $type = $options->getType();
      }
    }
    
  • Or, you could make it depend on values in constructor and leave out the argument:

    abstract class Cubique_Helper_Abstract {
        abstract public function execute();
    }
    
    class Cubique_Helper_Doctype extends Cubique_Helper_Abstract{
      public function __construct($type) {
        // since __construct() is not in abstract, it can be different
        // from every child class, which let's you handle dependencies
        $this->type = $type;
      }
      public function execute() {
        // you have $this->type here
      }
    }
    

The last alternative is my favorite. This way, you really make sure you have the dependencies and when it's time to execute() you don't have to give it any arguments.


I would not use func_get_args() since you lose track of dependencies. Example:

class Cubique_Helper_Doctype extends Cubique_Helper_Abstract {
  public function execute() {
    $args = func_get_args();
    $type = $args[0];
    $title = $args[1];
    $content = $args[2];
    // do something, for example
    echo $type; // will always echo "" if you miss arguments, but you really want a fatal error
  }
}

$d = new Cubique_Helper_Doctype();
$d->execute();
// this is a valid call in php, but it ruins your application.
// you **want** it to fail so that you know what's wrong (missing dependencies)

1 Comment

@stereofrog Cheers. I agree with you on "public" but "abstract" is useful for type hinting/making a contract with the abstract class. I saw your other answer on the topic and I think your proposed case there (something like if($_GET['bla'] == 'bla') $class = 'BlaClass'; makes sense for some but if you test your classes on beforehand, you'd know wether they work or not, and you can still benefit from having abstracts. There are worse, harder to test, cases implied by not compiling if you ask me :)
1

You could use func_get_arg so that the child class's method signature is the same.

Comments

1

When the number of arguments is different, you receive the error:

Fatal error: Declaration of Cubique_Helper_Doctype::execute() must be compatible with that of Cubique_Helper_Abstract::execute() in C:\wamp\www\tests\41.php on line 16

So your only option is to make the arguement an array and pass in it the actual arguments or make the declaration of execute with no parameters and mamipulate the sent arguments with func_get_args or func_get_arg and func_num_args

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.