PHP에서 컨스트럭터를 오버로드할 수 없는 이유는 무엇입니까?
저는 PHP에서 컨스트럭터를 과부하 시킬 수 있다는 모든 희망을 버렸습니다.그래서 제가 정말 알고 싶은 것은 그 이유입니다.
이유가 있긴 한 거야?본질적으로 나쁜 코드가 생성됩니까?그것을 허용하지 않는 것이 널리 받아들여지고 있는 언어 디자인입니까, 아니면 다른 언어들이 PHP보다 더 좋은가요?
PHP에서는 어떤 메서드도 오버로드할 수 없습니다.파라미터의 여러 조합을 전달하면서 PHP 오브젝트를 인스턴스화할 수 있도록 하려면 프라이빗 컨스트럭터와 함께 공장 패턴을 사용합니다.
예를 들어 다음과 같습니다.
public MyClass {
private function __construct() {
...
}
public static function makeNewWithParameterA($paramA) {
$obj = new MyClass();
// other initialization
return $obj;
}
public static function makeNewWithParametersBandC($paramB, $paramC) {
$obj = new MyClass();
// other initialization
return $obj;
}
}
$myObject = MyClass::makeNewWithParameterA("foo");
$anotherObject = MyClass::makeNewWithParametersBandC("bar", 3);
변수 인수를 사용하여 동일한 효과를 얻을 수 있습니다.강력한 타이핑이 없으면 기본 인수와 다른 모든 "작업 환경"을 고려할 때 추가하는 것은 큰 의미가 없습니다.
완성도를 높이기 위해 Fluent Interfaces를 제안합니다.여기서의 발상은,return $this;
을 사용하다 ★★★★★★★★★★★★★★★ 대신
$car1 = new Car('blue', 'RWD');
$car2 = new Car('Ford', '300hp');
(실패하지 않을 경우) 다음과 같은 작업을 수행할 수 있습니다.
$car = (new Car)
->setColor('blue')
->setMake('Ford')
->setDrive('FWD');
이렇게 하면 설정할 속성을 정확하게 선택할 수 있습니다.여러 가지 점에서 이것은 첫 번째 콜에 일련의 옵션을 전달하는 것과 비슷합니다.
$car = new Car(['make' => 'Ford', 'seats' => 5]);
진정한 오버로드는 실제로 PHP에서 지원되지 않습니다.@Pestilence에서 설명한 바와 같이 변수 인수를 사용할 수 있습니다.이를 극복하기 위해 다양한 옵션의 Associative Array를 사용하는 사람도 있습니다.
기능 파라미터의 디폴트값을 사용하여 이를 극복했습니다. »__constuct
에 필요한 파라미터를 먼저 나타냅니다..$param = null
.
class User
{
private $db;
private $userInput;
public function __construct(Database $db, array $userInput = null)
{
$this->db = $db;
$this->userInput = $userInput;
}
}
이는 다음과 같이 인스턴스화할 수 있습니다.
$user = new User($db)
또는
$user = new User($db, $inputArray);
이것은 완벽한 솔루션은 아니지만 오브젝트가 언제 구성되든 파라미터를 절대적으로 필요한 파라미터로 구분하고 그룹으로서 중요도 순으로 나열된 선택적 파라미터로 구분하여 작업을 수행했습니다.
그건 효과가 있다.
그들은 이 일을 말한다:
<?php
class A
{
function __construct()
{
$a = func_get_args();
$i = func_num_args();
if (method_exists($this,$f='__construct'.$i)) {
call_user_func_array(array($this,$f),$a);
}
}
function __construct1($a1)
{
echo('__construct with 1 param called: '.$a1.PHP_EOL);
}
function __construct2($a1,$a2)
{
echo('__construct with 2 params called: '.$a1.','.$a2.PHP_EOL);
}
function __construct3($a1,$a2,$a3)
{
echo('__construct with 3 params called: '.$a1.','.$a2.','.$a3.PHP_EOL);
}
}
$o = new A('sheep');
$o = new A('sheep','cat');
$o = new A('sheep','cat','dog');
// results:
// __construct with 1 param called: sheep
// __construct with 2 params called: sheep,cat
// __construct with 3 params called: sheep,cat,dog
?>
다들 만족하는 것 같긴 한데, 나한텐 그게 잘 안 먹혔어쨌든...제대로 작동시키면 과부하도...
모든 아르고몬트를 2차 함수 생성자에게 전달합니다.
<?php
//php do not automatically call parent class constructor at all if child class has constructor so you have to call parent class constructor explicitly, however parent class constructor is called automatically if child class has no constructor
class MyClass
{
function construct1($value1)
{
echo "<br/> dummy constructor is called with 1 arguments and it is $value1";
}
function construct2($value1,$value2)
{
echo "<br/> dummy constructor is called with 2 arguments and it is $value1, $value2";
}
function construct3($value1,$value2,$value3)
{
echo "<br/> dummy constructor is called with 3 arguments and it is $value1, $value2 , $value3";
}
public function __construct()
{
$NoOfArguments = func_num_args(); //return no of arguments passed in function
$arguments = func_get_args();
echo "<br/> child constructor is called $NoOfArguments";
switch ($NoOfArguments) {
case 1:
self::construct1($arguments[0]);
break;
case 2:
self::construct2($arguments[0],$arguments[1]);
break;
case 3:
self::construct3($arguments[0],$arguments[1],$arguments[2]);
break;
default:
echo "Invalid No of arguments passed";
break;
}
}
}
$c = new MyClass();
$c2 = new MyClass("ankit");
$c2 = new MyClass("ankit","Jiya");
$c2 = new MyClass("ankit","Jiya","Kasish");
?>
생성자에서 조건문을 사용한 다음 태스크를 수행할 수 있습니다.예.
class Example
{
function __construct($no_of_args)
{// lets assume 2
switch($no_of_args)
{
case 1:
// write your code
break;
case 2:
//write your 2nd set of code
break;
default:
//write your default statement
}
}
}
$object1 = new Example(1); // this will run your 1st case
$object2 = new Example(2); // this will run your 2nd case
기타 등등...
물론 __call() 및 __callStatic() 매직 메서드를 사용하여 PHP의 함수를 오버로드할 수 있습니다.조금 까다롭지만 구현은 원하는 대로 실행할 수 있습니다.다음은 공식 PHP.net 웹사이트에 있는 자료입니다.
https://www.php.net/manual/en/language.oop5.overloading.php#object.call
다음으로 스태틱 방식과 비 스태틱 방식 모두에서 사용할 수 있는 예를 제시하겠습니다.
class MethodTest
{
public function __call($name, $arguments)
{
// Note: value of $name is case sensitive.
echo "Calling object method '$name' "
. implode(', ', $arguments). "\n";
}
/** As of PHP 5.3.0 */
public static function __callStatic($name, $arguments)
{
// Note: value of $name is case sensitive.
echo "Calling static method '$name' "
. implode(', ', $arguments). "\n";
}
}
$obj = new MethodTest;
$obj->runTest('in object context');
MethodTest::runTest('in static context'); // As of PHP 5.3.0
또한 __construct()에서 다음 코드를 사용하여 이를 컨스트럭터에 적용할 수 있습니다.
$clsName = get_class($this);
$clsName->methodName($args);
꽤 쉬워요.모든 인스턴스에서 호출한 함수를 사용하지 않고 호출한 메서드로 클래스의 클론 복사본을 만들기 위해 __clone()을 구현할 수도 있습니다.
현재 PHP에 대한 완전성을 위해 이 답변을 추가하면 이후 버전의 PHP부터 실제로 컨스트럭터를 오버로드할 수 있습니다.다음 코드는 이해에 도움이 됩니다.
<?php
class A
{
function __construct()
{
$a = func_get_args();
$i = func_num_args();
if (method_exists($this,$f='__construct'.$i)) {
call_user_func_array(array($this,$f),$a);
}
}
function __construct1($a1)
{
echo('__construct with 1 param called: '.$a1.PHP_EOL);
}
function __construct2($a1,$a2)
{
echo('__construct with 2 params called: '.$a1.','.$a2.PHP_EOL);
}
function __construct3($a1,$a2,$a3)
{
echo('__construct with 3 params called: '.$a1.','.$a2.','.$a3.PHP_EOL);
}
}
$o = new A('sheep');
$o = new A('sheep','cat');
$o = new A('sheep','cat','dog');
?>
출력:
__construct with 1 param called: sheep
__construct with 2 params called: sheep,cat
__construct with 3 params called: sheep,cat,dog
public function construct1($user , $company)
{
dd("constructor 1");
$this->user = $user;
$this->company = $company;
}
public function construct2($cc_mail , $bcc_mail , $mail_data,$user,$company)
{
dd('constructor 2');
$this->mail_data=$mail_data;
$this->user=$user;
$this->company=$company;
$this->cc_mail=$cc_mail;
$this->bcc_mail=$bcc_mail;
}
public function __construct()
{
$NoOfArguments = func_num_args(); //return no of arguments passed in function
$arguments = func_get_args();
switch ($NoOfArguments) {
case 1:
self::construct1($arguments[0]);
break;
case 5:
self::construct2($arguments[0],$arguments[1],$arguments[2],$arguments[3],$arguments[4]);
break;
default:
echo "Invalid No of arguments passed";
break;
}
이 경우 인터페이스를 사용할 것을 권장합니다.
interface IExample {
public function someMethod();
}
class oneParamConstructor implements IExample {
public function __construct(private int $someNumber) {
}
public function someMethod(){
}
}
class twoParamConstructor implements IExample {
public function __construct(private int $someNumber, string $someString) {
}
public function someMethod(){
}
}
코드보다 커집니다.
function doSomething(IExample $example) {
$example->someMethod();
}
$a = new oneParamConstructor(12);
$b = new twoParamConstructor(45, "foo");
doSomething($a)
doSomething($b)
내가 아는 한, PHP 개발자들이 그 기능을 포함하지 않았다는 이유만으로 PHP에서 컨스트럭터의 오버로드는 허용되지 않는다.이것은 PHP에 관한 많은 불만 중 하나이다.
트릭과 회피책에 대해서는 들어봤지만 OOP의 의미에서의 진정한 오버로드가 누락되어 있습니다.향후 버전에는 포함될지도 모릅니다.
PHP에서 컨스트럭터 오버로드의 잠재적인 대체물로 default 인수를 사용하여 컨스트럭터를 사용할 수도 있다고 생각합니다.
그러나 진정한 컨스트럭터 오버로드가 PHP에서 지원되지 않는 것은 매우 슬픈 일입니다.
<?php
class myClass {
public $param1 = 'a';
public $param2 = 'b';
public function __construct($param1 = NULL, $param2 = NULL) {
if ($param1 == NULL && $param2 == NULL) {
// $this->param1 = $param1;
// $this->param2 = $param2;
} elseif ($param1 == NULL && $param2 !== NULL) {
// $this->param1 = $param1;
$this->param2 = $param2;
} elseif ($param1 !== NULL && $param2 == NULL) {
$this->param1 = $param1;
// $this->param2 = $param2;
} else {
$this->param1 = $param1;
$this->param2 = $param2;
}
}
}
// $myObject = new myClass();
// $myObject = new myClass(NULL, 2);
$myObject = new myClass(1, '');
// $myObject = new myClass(1, 2);
echo $myObject->param1;
echo "<br />";
echo $myObject->param2;
?>
저는 OOP 전문가는 아니지만 오버로드란 입력으로 받는 파라미터에 따라 다르게 동작하는 메서드의 능력을 의미합니다.이것은 PHP에서는 매우 가능합니다.PHP는 강력한 타이핑이 없기 때문에 입력 유형을 선언하지 않을 뿐이며, 모든 오버로드는 컴파일 시간이 아닌 런타임에 이루어집니다.
언급URL : https://stackoverflow.com/questions/2169448/why-cant-i-overload-constructors-in-php
'programing' 카테고리의 다른 글
vue.js의 로그아웃 버튼으로 main.js의 인스턴스에 액세스합니다. (0) | 2022.09.25 |
---|---|
문자열이 PHP의 이메일 주소인지 확인합니다. (0) | 2022.09.25 |
Cake용으로 작성된 기존 MySQL 데이터베이스에서 ER 다이어그램 생성PHP (0) | 2022.09.25 |
http 응답을 보낸 후 php 처리를 계속합니다. (0) | 2022.09.25 |
vuex 및 Vue-native-websocket 플러그인에서 WebSockets 데이터 수신 (0) | 2022.09.24 |