16

Can I have two methods sharing the same name, but with different arguments?

One would be public static and would take 2 arguments, the other one just public and takes only one argument

example

class product{

  protected
    $product_id;

  public function __construct($product_id){
    $this->product_id = $product_id;
  }

  public static function getPrice($product_id, $currency){
    ...
  }

  public function getPrice($currency){
    ...
  }

}
Alex
  • 64,868
  • 164
  • 416
  • 621
  • PHP does not support multiple method signatures as far as I understand. – Jared Farrish Dec 07 '11 at 01:10
  • 2
    See: [Multiple Method Signatures For A Single Abstract Function/Abstract Overloading](http://stackoverflow.com/questions/4450304/multiple-method-signatures-for-a-single-abstract-function-abstract-overloading) – Jared Farrish Dec 07 '11 at 01:11
  • 4
    Only by utilizing the `__call` and `__callStatic` handler and implementing the signature handling yourself. Would still need two distinct real method names. – mario Dec 07 '11 at 01:11
  • so __call runs when the function is called in object context and __callStatic when the function is called like class::function? I could do that, but I don't know how to determine the number of arguments for each method, because I would have multiple methods of this kind, not just two :) And some of them take like 3-4 arguments... – Alex Dec 07 '11 at 01:16

4 Answers4

13

No. PHP does not support classic overloading. (It does implement something else that is called overloading.)

You can get the same result by using func_get_args() and it's related functions though:

function ech()
{
  $a = func_get_args();
  for( $t=0;$t<count($a); $t++ )
  {
    echo $a[$t];
  }
}
EToreo
  • 2,826
  • 4
  • 29
  • 36
8

I'm just giving you the super lazy option:

function __call($name, $args) {
    $name = $name . "_" . implode("_", array_map("gettype", $args)));
    return call_user_func_array(array($this, $name), $args);
}

That would for example invoke the real function name getPrice_string_array for two parameters of that type. That's sort of what languages with real method signature overloading support would do behind the scenes.

Even lazier would be just counting the arguments:

function __callStatic($name, $args) {
    $name = $name . "_" . count($args);
    return call_user_func_array(array($this, $name), $args);
}

That would invoke getPrice_1 for 1 argument, or getPrice_2 for, you guessed it, two arguments. This might already suffice for most use cases. Of course you can combine both alternatives, or make it more clever by search for all alternative real method names.

If you want to keep your API pretty and user-friendly implementing such elaborate workarounds is acceptable. Very much so.

mario
  • 141,508
  • 20
  • 234
  • 284
  • thank you, but __callstatic doesn't work, "$this" is undefined. Replacing it with 'self' doesnt seem to work either, maybe because I added these magic methods in the parent class? – Alex Dec 07 '11 at 01:36
  • No, of course. `$this` was wrong in that context. Late static binding might not work with call_user_func_array. In that case you can only duplicate the `__callStatic` in every subclass as required. – mario Dec 07 '11 at 01:40
  • ok it works with `call_user_func_array(array('static', $name), $args);` but the problem is that I cannot check if the method exists :( apparently method_exists doesn't recognize 'static' – Alex Dec 07 '11 at 01:44
  • You might try `is_callable` instead. (It's supposedly context aware.) But you might be out of luck with both. That's kind of an uncommon use case already. -- Ah, okay. Good idea too. – mario Dec 07 '11 at 01:47
1

PHP currently doesn't support overloading in known way, but you can still achieve your goal by using magic methods.

From PHP5 manual: overloading.

SIFE
  • 5,367
  • 7
  • 31
  • 44
0

You could, kind of... I consider it very much "hack" solutions, but you could make a single function and assign a standard value, that wouldn't otherwise be okay to use, to the parameters as needed. Then if you do not pass the function a certain parameter, it will be set to fx "-1".

public function getPrice($product_id = "-1", $currency) {
    if($product_id = "-1") {
        //do something
    }else {
        //do something
    }
}

Or if you really need one method to be static, you can make a method that evaluates which method to call and call that instead of your getPrice:

public function whichGetPrice($product_id = "-1", $currency) {
    if($product !== "-1") {
        getStaticPrice($product_id, $currency);
    }else {
        getPrice($currency);
    }
}

Like I said, very much "hack" solutions. It's not exactly pretty, nor a way people would expect you to do it. So I wouldn't necessarily recommend it, but it can help you do what you want.

RasmusLD
  • 31
  • 6