PHP 함수 오버로딩
PHPPHP 함수 오버로딩
C ++ 배경부터;) 어떻게 PHP 함수를 오버로드 할 수 있습니까?
인자가 있다면 함수 정의 하나, 인자가 없다면 또 다른 함수 정의? PHP로 가능합니까? 또는 다른 경우 $ _GET 및 POST 전달 된 매개 변수가 있는지 확인하려면 사용해야합니까 ?? 그들을 연관 시키시겠습니까?
해결법
-
==============================
1.PHP 함수를 오버로드 할 수 없습니다. 함수 시그니처는 이름에만 기반을두고 인수 목록을 포함하지 않으므로 동일한 이름을 가진 두 개의 함수를 가질 수 없습니다. 클래스 메소드 오버로딩은 다른 많은 언어와 PHP에서 다릅니다. PHP는 같은 단어를 사용하지만 다른 패턴을 설명합니다.
PHP 함수를 오버로드 할 수 없습니다. 함수 시그니처는 이름에만 기반을두고 인수 목록을 포함하지 않으므로 동일한 이름을 가진 두 개의 함수를 가질 수 없습니다. 클래스 메소드 오버로딩은 다른 많은 언어와 PHP에서 다릅니다. PHP는 같은 단어를 사용하지만 다른 패턴을 설명합니다.
그러나 변수 수를 취하는 가변 함수를 선언 할 수 있습니다. func_num_args () 및 func_get_arg ()를 사용하여 전달 된 인수를 가져 와서 정상적으로 사용합니다.
예 :
function myFunc() { for ($i = 0; $i < func_num_args(); $i++) { printf("Argument %d: %s\n", $i, func_get_arg($i)); } } /* Argument 0: a Argument 1: 2 Argument 2: 3.5 */ myFunc('a', 2, 3.5);
-
==============================
2.PHP는 전통적인 메서드 오버로딩을 지원하지 않지만 원하는 것을 얻을 수있는 방법 중 하나는 __call 매직 메서드를 사용하는 것입니다.
PHP는 전통적인 메서드 오버로딩을 지원하지 않지만 원하는 것을 얻을 수있는 방법 중 하나는 __call 매직 메서드를 사용하는 것입니다.
class MyClass { public function __call($name, $args) { switch ($name) { case 'funcOne': switch (count($args)) { case 1: return call_user_func_array(array($this, 'funcOneWithOneArg'), $args); case 3: return call_user_func_array(array($this, 'funcOneWithThreeArgs'), $args); } case 'anotherFunc': switch (count($args)) { case 0: return $this->anotherFuncWithNoArgs(); case 5: return call_user_func_array(array($this, 'anotherFuncWithMoreArgs'), $args); } } } protected function funcOneWithOneArg($a) { } protected function funcOneWithThreeArgs($a, $b, $c) { } protected function anotherFuncWithNoArgs() { } protected function anotherFuncWithMoreArgs($a, $b, $c, $d, $e) { } }
-
==============================
3.함수를 과도하게로드하려면 기본적으로 매개 변수를 null로 전달하십시오.
함수를 과도하게로드하려면 기본적으로 매개 변수를 null로 전달하십시오.
class ParentClass { function mymethod($arg1 = null, $arg2 = null, $arg3 = null) { if( $arg1 == null && $arg2 == null && $arg3 == null ){ return 'function has got zero parameters <br />'; } else { $str = ''; if( $arg1 != null ) $str .= "arg1 = ".$arg1." <br />"; if( $arg2 != null ) $str .= "arg2 = ".$arg2." <br />"; if( $arg3 != null ) $str .= "arg3 = ".$arg3." <br />"; return $str; } } } // and call it in order given below ... $obj = new ParentClass; echo '<br />$obj->mymethod()<br />'; echo $obj->mymethod(); echo '<br />$obj->mymethod(null,"test") <br />'; echo $obj->mymethod(null,'test'); echo '<br /> $obj->mymethod("test","test","test")<br />'; echo $obj->mymethod('test','test','test');
-
==============================
4.어떤 사람들에게는 hackish가 될 수도 있지만 Cakephp가 어떤 기능을 수행 하는지를이 방법을 통해 알게되었고, 내가 만든 유연성을 좋아하기 때문에 그것을 적용했습니다.
어떤 사람들에게는 hackish가 될 수도 있지만 Cakephp가 어떤 기능을 수행 하는지를이 방법을 통해 알게되었고, 내가 만든 유연성을 좋아하기 때문에 그것을 적용했습니다.
아이디어는 당신이 인수, 배열, 객체 등등의 다른 유형을 가지고있다, 그러면 당신은 당신이 통과되고 거기에서부터 이동 한 것을 탐지합니다.
function($arg1, $lastname) { if(is_array($arg1)){ $lastname = $arg1['lastname']; $firstname = $arg1['firstname']; } else { $firstname = $arg1; } ... }
-
==============================
5.Real Overload (버전 3.8) "확장없는"+ "클로저 지원"
Real Overload (버전 3.8) "확장없는"+ "클로저 지원"
/******************************* * author : hishamdalal@gmail.com * version : 3.8 * create on : 2017-09-17 *****************************/ class Overloadable { static function call($obj, $method, $params=null) { $class = get_class($obj); // Get real method name $suffix_method_name = $method.self::getMethodSuffix($method, $params); if (method_exists($obj, $suffix_method_name)) { // Call method return call_user_func_array(array($obj, $suffix_method_name), $params); }else{ throw new Exception('Tried to call unknown method '.$class.'::'.$suffix_method_name); } } static function getMethodSuffix($method, $params_ary=array()) { $c = '__'; if(is_array($params_ary)){ foreach($params_ary as $i=>$param){ // Adding special characters to the end of method name switch(gettype($param)){ case 'array': $c .= 'a'; break; case 'boolean': $c .= 'b'; break; case 'double': $c .= 'd'; break; case 'integer': $c .= 'i'; break; case 'NULL': $c .= 'n'; break; case 'object': // Support closure parameter if($param instanceof Closure ){ $c .= 'c'; }else{ $c .= 'o'; } break; case 'resource': $c .= 'r'; break; case 'string': $c .= 's'; break; case 'unknown type':$c .= 'u'; break; } } } return $c; } // Get a reference variable by name static function &refAccess($var_name) { $r =& $GLOBALS["$var_name"]; return $r; } } class test { private $name = 'test-1'; // Call Overloadable class // you must copy this method in your class to activate overloading function __call($method, $args) { return Overloadable::call($this, $method, $args); } // func(closure) function func__c(Closure $callback) { pre("func__c(".print_r($callback, 1).");", 'print_r(Closure)'); return $callback($this->name); } } //---------------------------------------------------------- // Start $t = new test; pre($t->func(function($n){ return strtoupper($n);}), 'Closure'); //---------------------------------------------------------- function pre($mixed, $title=null, $print=true){ $output = ""; if(empty($mixed)){ $output .= "<div><h3>-->Empty $title<--</h3></div>"; if($print) echo $output; else return $output; } $output .= "<fieldset>"; if($title){$output .= "<legend><h2>$title</h2></legend>";} $output .= '<pre>'; $output .= print_r($mixed, 1); $output .= '</pre>'; $output .= "</fieldset>"; if($print) echo $output; else return $output; } //----------------------------------------------------------
산출:
---- print_r(Closure) ---- func__c(Closure Object ( [parameter] => Array ( [$n] => ) ) ); ---- Closure ---- TEST-1
Real Overload "확장하지 않음"(버전 3.7)
<?php /******************************* * author : hishamdalal@gmail.com * version : 3.7 * date : 2014-12-01 *****************************/ class Overloadable { static function call($obj, $method, $params=null) { // Get real method name $suffix_method_name = $method.self::getMethodSuffix($method, $params); if (method_exists($obj, $suffix_method_name)) { // Call method return call_user_func_array(array($obj, $suffix_method_name), $params); #return $obj->$suffix_method_name($params); } else { $class = get_class($obj); throw new Exception('Tried to call unknown method '.$class.'::'.$suffix_method_name); } } static function getMethodSuffix($method, $params_ary=array()) { $c = '__'; if( is_array($params_ary) ) { foreach($params_ary as $i=>$param){ // Adding special characters to the end of method name switch(gettype($param)){ case 'array': $c .= 'a'; break; case 'boolean': $c .= 'b'; break; case 'double': $c .= 'd'; break; case 'integer': $c .= 'i'; break; case 'NULL': $c .= 'n'; break; case 'object': $c .= 'o'; break; case 'resource': $c .= 'r'; break; case 'string': $c .= 's'; break; } } } return $c; } // Get a reference variable by name static function &refAccess($var_name) { $r =& $GLOBALS["$var_name"]; return $r; } } class test { // Call Overloadable class // you must copy this method in your class to activate overloading function __call($method, $args) { return Overloadable::call($this, $method, $args); } // myFunction(void) function myFunction__() { echo 'myFunction(void)'; } // myFunction(integer) function myFunction__i($int) { echo 'myFunction(integer='.$int.')'; } // myFunction(string) function myFunction__s($string) { echo 'myFunction(string='.$string.')'; } // myFunction(string) function myFunction__so($string, $object) { echo 'myFunction(string='.$string.', object='.get_class($object).')'; echo '<pre>Object: '; print_r($object); echo '</pre>'; } // anotherFunction(array) function anotherFunction__a($array) { echo 'anotherFunction('.print_r($array, 1).')'; $array[0]++; // change the reference value $array['val']++; // change the reference value } // anotherFunction(string, integer) function anotherFunction__si($key, $value) { echo 'anotherFunction(string='.$key.', integer='.$value.')'; // Get a reference $a2 =& Overloadable::refAccess($key); // $a2 =& $GLOBALS['val']; $a2 *= 3; // change the reference value } } //---------------------------------------------------------- // Some data to work with: $val = 10; class obj { private $x=10; } //---------------------------------------------------------- // Start $t = new test; // Call first method with no args: $t->myFunction(); // Output: myFunction(void) echo '<hr>'; $t->myFunction($val); // Output: myFunction(integer=10) echo '<br>'; $t->myFunction("hello"); // Output: myFunction(string=hello) echo '<br>'; $t->myFunction("str", new obj()); /* Output: myFunction(string=str, object=obj) Object: obj Object ( [x:obj:private] => 10 ) */ ## Passing by Reference: echo '<hr>'; echo '$val='.$val; // Output: $val=10 echo '<br>'; $t->anotherFunction(array(&$val, 'val'=>&$val)); // Output: anotherFunction(Array ( [0] => 10 [val] => 10 ) ) echo '<br>'; echo '$val='.$val; // Output: $val=12 echo '<hr>'; $t->anotherFunction('val', $val); // Output: anotherFunction(string=val, integer=12) echo '<br>'; echo '$val='.$val; // Output: $val=36
Real Overload (버전 3.5) :
/******************************* * author : hishamdalal@gmail.com * version : 3.5 * date : 2014-11-16 *****************************/ class Overloadable { // Magic Method public function __call($method, $params) { $class = get_class($this); // Get real method name $suffix_method_name = $method.$this->getMethodSuffix($method, $params); if (method_exists($this, $suffix_method_name)){ // Call method return call_user_func_array(array($this, $suffix_method_name), $params); }else{ throw new Exception('Tried to call unknown method '.$class.'::'.$suffix_method_name); } } function getMethodSuffix($method, $params_ary=array()){ $c = '__'; if(is_array($params_ary)){ foreach($params_ary as $i=>$param){ // Adding special characters to the end of method name switch(gettype($param)){ case 'integer': $c .= 'i'; break; case 'double': $c .= 'd'; break; case 'string': $c .= 's'; break; case 'array': $c .= 'a'; break; case 'object': $c .= 'o'; break; case 'resource': $c .= 'r'; break; case 'NULL': $c .= 'n'; break; } } } return $c; } // Get reference variable by name function &refAccess($var_name){ $r =& $GLOBALS["$var_name"]; return $r; } } //------------------------------------------------------------------------// ## Inherit "Overloadable" class to enable overloading class test extends Overloadable { // myFunction(void) function myFunction__() { echo "Hi<br>"; } // myFunction(integer, string) function myFunction__is($a, $s) { echo "$a, $s<br>"; } // myFunction(array) function myFunction__a($a) { $a[0]++; // change the reference value $a[1]++; // change value locally (method scope) } // myFunction(integer) function myFunction__i($b) { // $GLOBALS['val2'] $b2 =& $this->refAccess('val2'); $b2 *= 3; // change the reference value } // myFunction(string, string) function myFunction__ss($a, $b) { // $this->refAccess('obj')->plus() $this->refAccess($a)->plus(); #$b1 =& $GLOBALS["$b"]; $b1 =& $this->refAccess($b); $b1++; $b1++; } // myFunction(object, integer, array) function myFunction__oia($a, $b, $ary) { // Get arguments names $obj_name = $ary[0]; $val_name = $ary[1]; // Get argument reference $a1 =& $this->refAccess($obj_name); $a1->plus(); $b1 =& $this->refAccess($val_name); $b1+= $b; } // Just a normal method function welcome(){ echo "Welcome!"; } } //------------------------------------------------------------------------// // Some data types to work with: class obj { private $v=0; function plus(){ $this->v++; } function result(){ return $this->v; } } $val = 10; $val2 = 10; $obj = new obj(); // Show Default values echo "\$val = $val, \$val2 = $val2, "; echo 'obj->v =' . $obj->result()."<hr>"; //------------------------------------------------------------------------// // Start $t = new test(); // Call first method with no args: echo 'myFunction__():<br>'; $t->myFunction(); echo "<hr>"; echo 'myFunction__is(integer, string):<br>'; $t->myFunction($val, 'text'); echo "\$val = $val, \$val2 = $val2<hr>"; echo 'myFunction__i(integer):<br>'; $t->myFunction($val); echo "\$val = $val, \$val2 = $val2<hr>"; ## Passing by Reference: // 1) The best way to pass arguments echo 'myFunction__a(array):<br>'; //Passing first item by reference $t->myFunction(array(&$val, $val2)); echo "\$val = $val, \$val2 = $val2<hr>"; // 2) Passing arguments names echo 'myFunction__ss(string, string):<br>'; // Pass object name and variable name $t->myFunction('obj', 'val'); echo "\$val = $val, \$val2 = $val2, "; echo 'obj->v =' . $obj->result()."<hr>"; // 3) Passing arguments values and names echo 'myFunction__oia(object, integer, array):<br>'; // Pass object, integer values and passing there names as array $t->myFunction($obj, $val, array('obj', 'val')); echo "\$val = $val, \$val2 = $val2, "; echo 'obj->v =' . $obj->result()."<hr>"; // Just a normal method echo 'welcome():<br>'; $t->welcome();
Real Overload (버전 3.1) :
/******************************* * author : hishamdalal@gmail.com * version : 3.1 * date : 2013-04-11 *****************************/ class overloadable { protected $fname = null; protected $fargs = array(); //--------------------------------------------------// function set($obj, $fname, $args){ $n = ''; $type = $this->getType($args); $n = "\$o = new $obj();\n"; $n .= "if(method_exists(\$o, '$fname"."_$type')){\n"; $n .= "\t\$r = \$o->$fname"."_$type(". $this->getArgsName($args) .");\n"; $n .= "}else{\n\t\$r = null;\n"; $n .= "\ttrigger_error('function ".$fname."_".$type." is not exist!');\n}"; eval("\$r = $n;"); return $r; } //--------------------------------------------------// function getType($args) { $argType = array(); foreach($args as $i=>$val) { $argType[$i][] = $this->getSuffix($val, $i) ; } $s = ''; if(is_array($argType)){ foreach($argType as $type){ $s .= implode('', $type); } return $s; } return implode('', $argType); } //--------------------------------------------------// function getSuffix($byValarg, $i) { if( is_numeric($byValarg) ) { $type = 'N'; $this->fargs['N'.$i] = $byValarg; } elseif( is_array($byValarg) ) { $type = 'A'; $this->fargs['A'.$i] = $byValarg; } elseif( is_object($byValarg) ) { $type = 'O'; $this->fargs['O'.$i] = $byValarg; } elseif( is_resource($byValarg) ) { $type = 'R'; $this->fargs['R'.$i] = $byValarg; } else { $type = 'S'; $this->fargs['S'.$i] = $byValarg; } return $type; } //--------------------------------------------------// function getArgsName($args){ $r = array(); $ary = array_keys($this->fargs); foreach( $ary as $k=>$v){ $r[]='$this->fargs["'.$v.'"]'; } return implode(", ", $r); } //--------------------------------------------------// function __call($name, $args){ $this->fargs = array(); return $this->set(get_class($this), $name, $args); } //--------------------------------------------------// } class test2 extends overloadable { function foo_(){ echo 'foo - no args'; } function foo_S($s){ echo "foo - one string $s"; } function foo_SS($s1, $s2){ echo "foo - tow strings $s1, $s2"; } function foo_SN($s, $n){ echo "foo - string and number $s, $n"; } function foo_A($ary){ print_r($ary); } function foo_AA($ary1, $ary2){ if(is_array($ary1) && is_array($ary2)){ echo "foo - tow arrays"; }else{echo 0;} } function foo_O($obj){ echo "foo - "; print_r($obj); } function hi(){ echo "hi - welcome!"; } } echo '<pre>'; $t = new test2(); echo '<br />foo_: '; print_r( $t->foo() ); echo '<br />foo_s: '; print_r( $t->foo('a') ); echo '<br />foo_ss: '; print_r( $t->foo('a', 'b') ); echo '<br />foo_sn: '; print_r( $t->foo('a', 2) ); echo '<br />foo_snn: '; print_r( $t->foo('s', 2, 9) ); echo '<br />foo_a: '; print_r( $t->foo(array(4,5,6,7)) ); echo '<br />foo_aa: '; print_r( $t->foo( array(5,6,7), array(8,9,10) ) ); echo '<br />foo_o: '; print_r( $t->foo($t) ); echo '<br />hi: '; print_r( $t->hi() );
-
==============================
6.이건 어때?
이건 어때?
function($arg = NULL) { if ($arg != NULL) { etc. etc. } }
-
==============================
7.PHP 5.6에서는 마지막 매개 변수로 splat 연산자를 사용할 수 있으며 func_get_args () 및 func_num_args ()를 사용하지 않아도됩니다.
PHP 5.6에서는 마지막 매개 변수로 splat 연산자를 사용할 수 있으며 func_get_args () 및 func_num_args ()를 사용하지 않아도됩니다.
function example(...$args) { count($args); // Equivalent to func_num_args() } example(1, 2); example(1, 2, 3, 4, 5, 6, 7);
인수를 풀 때도 사용할 수 있습니다.
$args[] = 1; $args[] = 2; $args[] = 3; example(...$args);
다음과 같습니다.
example(1, 2, 3);
-
==============================
8.
<?php class abs { public function volume($arg1=null, $arg2=null, $arg3=null) { if($arg1 == null && $arg2 == null && $arg3 == null) { echo "function has no arguments. <br>"; } else if($arg1 != null && $arg2 != null && $arg3 != null) { $volume=$arg1*$arg2*$arg3; echo "volume of a cuboid ".$volume ."<br>"; } else if($arg1 != null && $arg2 != null) { $area=$arg1*$arg2; echo "area of square = " .$area ."<br>"; } else if($arg1 != null) { $volume=$arg1*$arg1*$arg1; echo "volume of a cube = ".$volume ."<br>"; } } } $obj=new abs(); echo "For no arguments. <br>"; $obj->volume(); echo "For one arguments. <br>"; $obj->volume(3); echo "For two arguments. <br>"; $obj->volume(3,4); echo "For three arguments. <br>"; $obj->volume(3,4,5); ?>
-
==============================
9.PHP는 현재 과부하를 지원하지 않습니다. 희망이 다른 프로그래밍 언어와 같은 다른 버전에서 구현됩니다.
PHP는 현재 과부하를 지원하지 않습니다. 희망이 다른 프로그래밍 언어와 같은 다른 버전에서 구현됩니다.
이 라이브러리를 체크 아웃하면 클로저와 관련하여 PHP 오버로딩을 사용할 수 있습니다. https://github.com/Sahil-Gulati/Overloading
-
==============================
10.안타깝게도 C #에서는 PHP에서 과부하가 없습니다. 하지만 조금 트릭이있어. 인수를 기본 null 값으로 선언하고 함수에서이를 확인합니다. 그런 식으로 내 기능은 인수에 따라 다른 일을 할 수 있습니다. 다음은 간단한 예입니다.
안타깝게도 C #에서는 PHP에서 과부하가 없습니다. 하지만 조금 트릭이있어. 인수를 기본 null 값으로 선언하고 함수에서이를 확인합니다. 그런 식으로 내 기능은 인수에 따라 다른 일을 할 수 있습니다. 다음은 간단한 예입니다.
public function query($queryString, $class = null) //second arg. is optional { $query = $this->dbLink->prepare($queryString); $query->execute(); //if there is second argument method does different thing if (!is_null($class)) { $query->setFetchMode(PDO::FETCH_CLASS, $class); } return $query->fetchAll(); } //This loads rows in to array of class $Result = $this->query($queryString, "SomeClass"); //This loads rows as standard arrays $Result = $this->query($queryString);
from https://stackoverflow.com/questions/4697705/php-function-overloading by cc-by-sa and MIT license
'PHP' 카테고리의 다른 글
PHP에서 배열에 대한 + 연산자? (0) | 2018.09.12 |
---|---|
PHP에서 404에 대한 URL을 테스트하는 쉬운 방법은 무엇입니까? (0) | 2018.09.12 |
HTTP 응답을 보낸 후 PHP 처리 계속 (0) | 2018.09.12 |
PHP에서 비동기 GET 요청을하는 방법은 무엇입니까? (0) | 2018.09.12 |
사람들이 플래시 게임의 PHP 기반 최고 점수 테이블을 해킹하는 것을 막는 가장 좋은 방법은 무엇입니까? (0) | 2018.09.12 |