19

I want to be able to declare an abstract function in an parent class, with an unknown number of arguments:

abstract function doStuff(...);

and then define an implementation with a set of hinted arguments:

 /**
 * @param int $userID
 * @param int $serviceproviderID
 */
static function doStuff($userID, $serviceproviderID) {}

The best approach I've got so far is this,

abstract function doStuff();

 /**
 * @param int $userID
 * @param int $serviceproviderID
 */
static function doStuff() {
    $args = func_get_args();
    ...
}

But every time the function is called, I get a bunch of 'missing argument' warnings because of the hints. Is there a better way?

Edit: The question's wrong, please don't waste your time answering. The following is what I was looking for, and it seems to work without warnings.

abstract class Parent {
    abstract function doStuff();
}

/**
* @param type $arg1
* @param type $arg2
*/
class Child extends Parent {
    function doStuff($arg1, $arg2) {
        ...
    }
}
  • Have you considered taking your arguments in the form of array? – w0bni Aug 15 '11 at 18:17
  • 2
    Why would you define a function as abstract in an interface? Then again, an interface function must have the same declaration as its implementation. That's the whole idea of interfaces. I don't know what your goal is, but I think you must be trying to make your code as unclear and unusable as possible. – GolezTrol Aug 15 '11 at 18:21
  • Huh, sorry, I may have screwed this question up. I'm *not* getting any warnings, so I guess this approach is OK. I specifically want multiple, named arguments as it makes the code more readable. –  Aug 15 '11 at 18:21
  • When you really want to provide an abstract method with an unknown number of arguments, you probably didn't really thought about it. You usually define abstracts methods, so everyone can extends the class and everyone else can use any implementation without knowing their concrete details, but with an unknown number of arguments the users _must_ know the details. – KingCrunch Aug 15 '11 at 18:22
  • @GolezTrol - No, I miss-spoke. It's an abstract method in a parent class. –  Aug 15 '11 at 18:23
  • When you say you're getting "warnings" I assume you mean from your IDE or whatever editor you're using. That shouldn't be throwing PHP errors. The "correct" ways to do what you're attempting to do would be to either a) take a single variable all the time as an array of params for the function (as suggested above) or b) do what you've written already and use func_get_args to get your variables. – Brian Aug 15 '11 at 18:23
  • Changed the question to clarify. –  Aug 15 '11 at 18:24
  • 1
    OMG, look at php.net what is keyword `abstract` for. – kravemir Aug 15 '11 at 18:26
  • It seems perfectly reasonable to allow for arbitrary arguments in an interface. Let's say you have a parent which manages connecting to an api. It defines an abstract function: parseResults(), then you have children of that class: Customer, Order, Transaction. Those fetches will, by nature, return an arbitrary number of results but the underlying mechanism doesn't need to change. – eggmatters Nov 05 '15 at 17:30

2 Answers2

11

In PHP 5.6 and later, argument lists may include the ... token to denote that the function accepts a variable number of arguments.

You can apply this to an abstract class as follows:

abstract class AbstractExample {
    public function do_something(...$numbers);
}

The arguments will be passed into the given variable as an array.

Greg
  • 21,235
  • 17
  • 84
  • 107
  • 2
    Such functions are called [**Variadic functions**](http://php.net/manual/en/functions.arguments.php#functions.variable-arg-list) – Paul T. Rawkeen Jun 02 '16 at 08:40
  • 1
    Combined with [`list`](https://secure.php.net/manual/en/function.list.php), you can name the parameters of the implementing function in a single line: `list($firstParam, $secondParam) = $params;` – totymedli Apr 11 '18 at 17:41
9

According the comment

I specifically want multiple, named arguments as it makes the code more readable.

abstract public function foo ($a, $b=null, $c=null);

If you want to pass an arbitrary number of values, use arrays

abstract public function foo ($args);

You should avoid "unknown number of arguments", because it makes things more difficult, then necessary: method signatures in interfaces as well as abstract methods should give the user a hint, how the method will work with any implementation. Its an important part, that the user shouldn't need to know anything about the implementation details. But when the number of arguments changes with every implementation, he must know, how the concrete methods are implemented.

KingCrunch
  • 128,817
  • 21
  • 151
  • 173
  • 2
    Well, you *must* avoid having an unknown number of arguments in PHP because the language doesn't allow for it. But as a general coding technique it's perfectly acceptable in certain cases. – J.Steve Mar 13 '13 at 04:27
  • 2
    @J.Steve I don't know, if I get your point, but PHP allows it ^^ http://codepad.viper-7.com/UW1ghx – KingCrunch Mar 13 '13 at 08:34
  • 2
    I think the point is the only way you can deal with an "unknown" number of arguments is by stating that you expect exactly one argument (so that PHP knows it expects one argument)...it just happens that one argument can have any number of properties and values within it. Not technically true to say PHP allows for an unknown number of arguments. – niaccurshi Feb 24 '14 at 20:37