【问题标题】:Same named function with multiple arguments in PHPPHP中具有多个参数的同名函数
【发布时间】:2010-01-27 14:33:02
【问题描述】:

我从 Java 开始 OOP,现在我对 PHP 越来越感兴趣。是否可以像在 Java 中一样创建具有不同参数的函数的倍数?或者语言的解释/非类型化性质会阻止这种情况并导致冲突吗?

【问题讨论】:

  • 你能给我们举个例子吗?
  • 你的意思是多个函数同名吗?

标签: php function


【解决方案1】:

其他人都有很好的代码解释的答案。这是更高级术语的解释:Java 支持Method overloading,当您谈论具有相同名称但不同参数的函数时,这就是您所指的。由于 PHP 是一种动态类型的语言,因此这是不可能的。相反,PHP 支持Default arguments,您可以使用它来获得几乎相同的效果。

【讨论】:

  • 使用默认参数而不是重载是好的,可以让你正确地做你的多态性,但会使你的 PHP 应用程序不符合SOLID 标准,特别是开放/封闭原则
【解决方案2】:

如果您正在处理类,您可以使用 __call() 重载方法(参见 Overloading),例如:

class Foo {
    public function doSomethingWith2Parameters($a, $b) {

    }

    public function doSomethingWith3Parameters($a, $b, $c) {

    }

    public function __call($method, $arguments) {
      if($method == 'doSomething') {
          if(count($arguments) == 2) {
             return call_user_func_array(array($this,'doSomethingWith2Parameters'), $arguments);
          }
          else if(count($arguments) == 3) {
             return call_user_func_array(array($this,'doSomethingWith3Parameters'), $arguments);
          }
      }
   }    
}

那么你可以这样做:

$foo = new Foo();
$foo->doSomething(1,2); // calls $foo->doSomethingWith2Parameters(1,2)
$foo->doSomething(1,2,3); // calls $foo->doSomethingWith3Parameters(1,2,3)

这可能不是最好的例子,但__call 有时会非常方便。基本上,您可以使用它来捕获对不存在此方法的对象的方法调用。

但它不像 Java 那样简单。

【讨论】:

  • 这很好,因为如果 2 个参数的预期数据类型与 3 个参数不同,您不必担心检查类型
  • 如果我们简单地使用 return 语句会更容易:return $this->doSomethingWith2Parameters(implode(',', $arguments))return $this->doSomethingWith3Parameters(implode(',', $arguments))
  • @Don'tDownvoteMe:但这会将单个参数作为字符串传递,而不是多个参数(即$this->doSomethingWith2Parameters('1,2') 而不是$this->doSomethingWith2Parameters(1,2))。
  • 虽然我明白你的意思,但我认为如果我们使用implode,它会传递多个参数。看看我发布的答案。如果值作为单个参数传递,那么可能所有值在数组中都有一个键。但是在这种情况下,当我们使用 getter 时,它们都显示为键值对。因此,正在传递多个值。 stackoverflow.com/a/51995921/9106482
  • @Don'tDownvoteMe:不幸的是,您回答中的示例没有意义。 getArrayWithKey 只接受一个参数。此外,implode 只有在数组中实际有 > 1 个元素时才会有所不同。这就是我的意思以及call_user_func_arrayimplode之间区别的演示:repl.it/repls/SomeWelltodoBash
【解决方案3】:

简短回答:不可以。只能有一个具有给定名称的函数。

更长的答案:您可以通过创建一个复杂的包含系统来做到这一点,该系统包含具有正确数量参数的函数。或者,更好的是,您可以利用 PHP 允许参数的默认值以及可变数量的参数。

要利用默认值,只需在定义函数时为参数赋值:

function do_something($param1, $param2, $param3 = 'defaultvaule') {}

通常的做法是将具有默认值的参数放在函数声明的末尾,因为在调用函数时它们可能会被省略,并使使用它们的语法更清晰:

do_something('value1', 'value2'); // $param3 is 'defaultvaule' by default

您还可以使用func_num_args()func_get_arg() 发送可变数量的参数来获取参数:

<?php
  function dynamic_args() {
      echo "Number of arguments: " . func_num_args() . "<br />";
      for($i = 0 ; $i < func_num_args(); $i++) {
          echo "Argument $i = " . func_get_arg($i) . "<br />";
      }
  }

  dynamic_args("a", "b", "c", "d", "e");
?>

【讨论】:

    【解决方案4】:

    使用 php 无法实现以下操作

    function funcX($a){
        echo $a;
    }
    function funcX($a,$b){
        echo $a.$b;
    }
    

    改为这样做

    function funcX($a,$b=2){
        echo $a.$b;
    }
    

    funcX(1) 将显示12func(1,3) 将显示13

    【讨论】:

    • 最好让最后一个示例使用空字符串,这样如果只传递一个参数,您将获得更典型的预期结果:function funcX($a, $b=''){回声 $a.$b; }
    【解决方案5】:

    正如其他人所说,默认情况下不支持它。 Felix 使用__call() 的示例可能是最好的方法。

    否则,如果您使用的是相互继承的类,您总是可以重载子类中的方法名称。这也允许您调用父方法。

    以这些类为例...

    class Account {
      public function load($key,$type) {
        print("Loading $type Account: $key\n");
      }
    }
    
    class TwitterAccount extends Account {
      public $type = 'Twitter';
    
      public function load($key) {
        parent::load($key,$this->type);
      }
    }
    

    那你可以这样称呼他们……

    $account = new Account();
    $account->load(123,'Facebook');
    
    $twitterAccount = new TwitterAccount();
    $twitterAccount->load(123);
    

    你的结果将是......

    正在加载 Facebook 帐户:123 正在加载 Twitter 帐户:123

    【讨论】:

      【解决方案6】:

      不,这是不可能的,因为 PHP 无法从参数推断出你想要的函数(你没有指定你期望的类型)。但是,您可以为 php 中的参数赋予默认值。

      这样调用者可以给出不同数量的参数。不过,这将调用相同的函数。

      例子是:

      function test($a = true)
      

      如果给定 0 个参数,则默认为 true,如果给定 1 个参数,则采用调用值。

      【讨论】:

        【解决方案7】:

        我知道这是一个有点老的问题,但是从 php56 开始你可以:

        function sum(...$numbers) {
            $acc = 0;
            foreach ($numbers as $n) {
                $acc += $n;
            }
            return $acc;
        }
        
        echo sum(1, 2, 3, 4);
        

        参考:http://php.net/manual/en/functions.arguments.php

        【讨论】:

          【解决方案8】:

          在 PHP 中无法实现重载,但您可以使用默认参数值在某种程度上绕过它,如其他响应中所述。

          此解决方法的限制是当人们想要根据参数类型重载函数/方法时。这在 PHP 中是不可能的,需要自己测试参数类型,或者编写几个函数。函数 min 和 max 就是一个很好的例子:如果有一个数组类型的参数,它返回数组的最小值/最大值,否则返回参数的最小值/最大值。

          【讨论】:

            【解决方案9】:

            我有这样的想法:

            函数过程( $param1 , $type='array' ) { 开关($类型){ 案例“数组”: // 用它做点什么 休息; 案例“关联数组”: // 用它做点什么 休息; 案例“int_array”: // 用它做点什么 休息; 案例“字符串”: // 用它做点什么 休息; //等等等等... } }

            【讨论】:

              【解决方案10】:

              我有 2 个方法,getArrayWithoutKey,它将输出数组的所有条目而不提供任何键值。第二种方法getArrayWithKey 将使用键值从同一数组中输出特定条目。这就是我在那里使用方法重载的原因。

              class abcClass
              {
                      private $Arr=array('abc'=>'ABC Variable', 'def'=>'Def Variable');
              
              
                      public function setArr($key, $value)
                      {
                          $this->Arr[$key]=$value;
                      }
              
                      private function getArrWithKey($key)
                      {
                          return $this->Arr[$key];
                      }
                      private function getArrWithoutKey()
                      {
                          return $this->Arr;
                      }
              
                      //Method Overloading in PHP
              
                      public function __call($method, $arguments)
                      {
                          if($method=='getArr')
                          {
                                  if(count($arguments)==0)
                                  {
                                              return $this->getArrWithoutKey();
                                  }
                                  elseif(count($arguments)==1)
                                  {
                                              return $this->getArrWithKey(implode(',' , $arguments));
                                  }
                          }
              
                      }
              
              
              }
              
              /* Setting and getting values of array-> Arr[] */
              $obj->setArr('name', 'Sau');
              $obj->setArr('address', 'San Francisco');
              $obj->setArr('phone', 7777777777);
              echo $obj->getArr('name')."<br>";
              print_r( $obj->getArr());
              echo "<br>";
              

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2019-08-14
                • 1970-01-01
                • 2013-07-29
                • 2016-12-04
                • 1970-01-01
                • 2016-02-04
                • 1970-01-01
                相关资源
                最近更新 更多