【发布时间】:2010-01-27 14:33:02
【问题描述】:
我从 Java 开始 OOP,现在我对 PHP 越来越感兴趣。是否可以像在 Java 中一样创建具有不同参数的函数的倍数?或者语言的解释/非类型化性质会阻止这种情况并导致冲突吗?
【问题讨论】:
-
你能给我们举个例子吗?
-
你的意思是多个函数同名吗?
我从 Java 开始 OOP,现在我对 PHP 越来越感兴趣。是否可以像在 Java 中一样创建具有不同参数的函数的倍数?或者语言的解释/非类型化性质会阻止这种情况并导致冲突吗?
【问题讨论】:
其他人都有很好的代码解释的答案。这是更高级术语的解释:Java 支持Method overloading,当您谈论具有相同名称但不同参数的函数时,这就是您所指的。由于 PHP 是一种动态类型的语言,因此这是不可能的。相反,PHP 支持Default arguments,您可以使用它来获得几乎相同的效果。
【讨论】:
如果您正在处理类,您可以使用 __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 那样简单。
【讨论】:
return $this->doSomethingWith2Parameters(implode(',', $arguments)) 和 return $this->doSomethingWith3Parameters(implode(',', $arguments))。
$this->doSomethingWith2Parameters('1,2') 而不是$this->doSomethingWith2Parameters(1,2))。
implode,它会传递多个参数。看看我发布的答案。如果值作为单个参数传递,那么可能所有值在数组中都有一个键。但是在这种情况下,当我们使用 getter 时,它们都显示为键值对。因此,正在传递多个值。 stackoverflow.com/a/51995921/9106482
getArrayWithKey 只接受一个参数。此外,implode 只有在数组中实际有 > 1 个元素时才会有所不同。这就是我的意思以及call_user_func_array和implode之间区别的演示:repl.it/repls/SomeWelltodoBash
简短回答:不可以。只能有一个具有给定名称的函数。
更长的答案:您可以通过创建一个复杂的包含系统来做到这一点,该系统包含具有正确数量参数的函数。或者,更好的是,您可以利用 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");
?>
【讨论】:
使用 php 无法实现以下操作
function funcX($a){
echo $a;
}
function funcX($a,$b){
echo $a.$b;
}
改为这样做
function funcX($a,$b=2){
echo $a.$b;
}
funcX(1) 将显示12,func(1,3) 将显示13
【讨论】:
正如其他人所说,默认情况下不支持它。 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【讨论】:
不,这是不可能的,因为 PHP 无法从参数推断出你想要的函数(你没有指定你期望的类型)。但是,您可以为 php 中的参数赋予默认值。
这样调用者可以给出不同数量的参数。不过,这将调用相同的函数。
例子是:
function test($a = true)
如果给定 0 个参数,则默认为 true,如果给定 1 个参数,则采用调用值。
【讨论】:
我知道这是一个有点老的问题,但是从 php56 开始你可以:
function sum(...$numbers) {
$acc = 0;
foreach ($numbers as $n) {
$acc += $n;
}
return $acc;
}
echo sum(1, 2, 3, 4);
【讨论】:
在 PHP 中无法实现重载,但您可以使用默认参数值在某种程度上绕过它,如其他响应中所述。
此解决方法的限制是当人们想要根据参数类型重载函数/方法时。这在 PHP 中是不可能的,需要自己测试参数类型,或者编写几个函数。函数 min 和 max 就是一个很好的例子:如果有一个数组类型的参数,它返回数组的最小值/最大值,否则返回参数的最小值/最大值。
【讨论】:
我有这样的想法:
函数过程( $param1 , $type='array' ) { 开关($类型){ 案例“数组”: // 用它做点什么 休息; 案例“关联数组”: // 用它做点什么 休息; 案例“int_array”: // 用它做点什么 休息; 案例“字符串”: // 用它做点什么 休息; //等等等等... } }
【讨论】:
我有 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>";
【讨论】: