it-source

PHP 클래스 컨스트럭터가 부모 컨스트럭터를 호출하려면 어떻게 해야 합니까?

criticalcode 2023. 2. 2. 21:10
반응형

PHP 클래스 컨스트럭터가 부모 컨스트럭터를 호출하려면 어떻게 해야 합니까?

PHP의 클래스 생성자가 부모 생성자를 호출하지 않고 부모(대부?) 생성자를 호출하도록 해야 합니다.

// main class that everything inherits
class Grandpa 
{
    public function __construct()
    {

    }

}

class Papa extends Grandpa
{
    public function __construct()
    {
        // call Grandpa's constructor
        parent::__construct();
    }
}

class Kiddo extends Papa
{
    public function __construct()
    {
        // THIS IS WHERE I NEED TO CALL GRANDPA'S
        // CONSTRUCTOR AND NOT PAPA'S
    }
}

이게 이상한 일이라는 걸 알고 나쁜 냄새가 나지 않는 방법을 찾으려고 노력 중이지만 그래도 그게 가능한지 궁금합니다.

이 문제를 해결하려면 Papa에 부울 파라미터를 전달하여 컨스트럭터에 포함된 코드를 해석하고 싶지 않음을 나타냅니다.예:

// main class that everything inherits
class Grandpa 
{
    public function __construct()
    {

    }

}

class Papa extends Grandpa
{
    public function __construct($bypass = false)
    {
        // only perform actions inside if not bypassing
        if (!$bypass) {

        }
        // call Grandpa's constructor
        parent::__construct();
    }
}

class Kiddo extends Papa
{
    public function __construct()
    {
        $bypassPapa = true;
        parent::__construct($bypassPapa);
    }
}

하셔야 합니다.Grandpa::__construct()하다 이것은, ,, ,, 합니다.Papa- 할 때 - 할 때 - 수업할 때 - 수업할 때 - 수업할 때 - 수업할 때Papa 때문에 이 경우 해도 좋을 것 같습니다.__construct() 중에 되지만, "구축 중"은 "구축 중"으로 호출됩니다.Kiddo이 하지 않습니다.class는 이 작업을 수행하지 않습니다.

class Grandpa 
{
    public function __construct()
    {}
}

class Papa extends Grandpa
{
    public function __construct()
    {
        //call Grandpa's constructor
        parent::__construct();
    }
}

class Kiddo extends Papa
{
    public function __construct()
    {
        //this is not a bug, it works that way in php
        Grandpa::__construct();
    }
}

해결 방법Reflection.

<?php
class Grandpa 
{
    public function __construct()
    {
        echo "Grandpa's constructor called\n";
    }

}

class Papa extends Grandpa
{
    public function __construct()
    {
        echo "Papa's constructor called\n";

        // call Grandpa's constructor
        parent::__construct();
    }
}

class Kiddo extends Papa
{
    public function __construct()
    {
        echo "Kiddo's constructor called\n";

        $reflectionMethod = new ReflectionMethod(get_parent_class(get_parent_class($this)), '__construct');
        $reflectionMethod->invoke($this);
    }
}

$kiddo = new Kiddo();
$papa = new Papa();

나는 결국 그 문제를 해결할 다른 해결책을 생각해 냈다.

  • 나는 할아버지를 연장하는 중급반을 만들었다.
  • 그리고 아빠와 아이 둘 다 그 수업을 연장했다.
  • 아이는 Papa의 중간 기능이 필요했지만, 컨스트럭터가 마음에 들지 않아 클래스에는 추가 기능이 있고 둘 다 확장되어 있습니다.

더 추악한 질문에 대해 유효하지만 추악한 해결책을 제공한 다른 두 가지 답변을 상향 조정했습니다.

플래그를 사용하지 않고 사용자 환경에서 사용할 수 있는 다른 옵션:

<?php
// main class that everything inherits
class Grandpa 
{
    public function __construct(){
        $this->GrandpaSetup();
    }

    public function GrandpaSetup(){
        $this->prop1 = 'foo';
        $this->prop2 = 'bar';
    }
}

class Papa extends Grandpa
{
    public function __construct()
    {
        // call Grandpa's constructor
        parent::__construct();
        $this->prop1 = 'foobar';
    }

}
class Kiddo extends Papa
{
    public function __construct()
    {
        $this->GrandpaSetup();
    }
}

$kid = new Kiddo();
echo "{$kid->prop1}\n{$kid->prop2}\n";

"too much php"에 동의합니다.이것을 시도해 보세요.

class Grandpa 
{
    public function __construct()
    {
        echo 'Grandpa<br/>';
    }

}

class Papa extends Grandpa
{
    public function __construct()
    {
        echo 'Papa<br/>';
        parent::__construct();
    }
}

class Kiddo extends Papa
{
    public function __construct()
    {
        // THIS IS WHERE I NEED TO CALL GRANDPA'S
        // CONSTRUCTOR AND NOT PAPA'S
        echo 'Kiddo<br/>';
        Grandpa::__construct();
    }
}

$instance = new Kiddo;

예상대로 결과가 나왔습니다.

꼬마야

할아버지

이것은 기능이지 버그가 아닙니다.참조해 주세요.

https://bugs.php.net/bug.php?id=42016

그것은 단지 그것이 작동하는 방식이다.이 콜 버전이 올바른 컨텍스트에서 발신되고 있는 것을 인식했을 경우, 이 콜버전은 스태틱콜을 강제하지 않습니다.

대신, 이것은 단순히 이것을 가지고 있고 그것에 만족할 것이다.

parent::parent()는 같은 방법으로 동작합니다.메서드를 스태틱으로 정의할 필요는 없지만 같은 컨텍스트에서 호출할 수 있습니다.더 흥미로운 정보를 얻으려면 다음을 시도해 보십시오.

class Grandpa 
{
    public function __construct()
    {
        echo 'Grandpa<br/>';
        Kiddo::hello();
    }

}

class Papa extends Grandpa
{
    public function __construct()
    {
        echo 'Papa<br/>';
        parent::__construct();
    }
}

class Kiddo extends Papa
{
    public function __construct()
    {
        // THIS IS WHERE I NEED TO CALL GRANDPA'S
        // CONSTRUCTOR AND NOT PAPA'S
        echo 'Kiddo<br/>';
        Grandpa::__construct();
    }

    public function hello()
    {
        echo 'Hello<br/>';
    }
}

$instance = new Kiddo;

또, 다음과 같이 동작합니다.

꼬마야

할아버지

안녕하세요.

그러나 새 Papa를 초기화하려고 하면 E_STRICT 오류가 발생합니다.

$papa = new Papa;

엄격한 표준: 비정적 메서드 Chid::hello()는 호환되지 않는 컨텍스트에서 $this를 가정하여 정적으로 호출해서는 안 됩니다.

instance of를 사용하여 부모 메서드에서 Children::method()를 호출할 수 있는지 여부를 결정할 수 있습니다.

if ($this instanceof Kiddo) Kiddo::hello();

이를 위한 더 쉬운 해결책이 있지만, 현재 클래스가 얼마나 많은 상속을 받았는지 정확히 알아야 합니다.다행히 get_parent_class() 인수를 사용하면 클래스 배열 멤버를 인스턴스 자체뿐만 아니라 문자열로도 클래스 이름으로 만들 수 있습니다.

상속 객체의 인스턴스화된 범위 내에서는 이 특정 케이스의 차이는 무시할 수 있지만, 이는 본질적으로 클래스의 __construct() 메서드를 정적으로 호출하는 것에 의존한다는 점에 유의하십시오(ah, PHP).

다음 사항을 고려하십시오.

class Foo {
    var $f = 'bad (Foo)';

    function __construct() {
        $this->f = 'Good!';
    }
}

class Bar extends Foo {
    var $f = 'bad (Bar)';
}

class FooBar extends Bar {
    var $f = 'bad (FooBar)';

    function __construct() {
        # FooBar constructor logic here
        call_user_func(array(get_parent_class(get_parent_class($this)), '__construct'));
    }
}

$foo = new FooBar();
echo $foo->f; #=> 'Good!'

debug_backtrace()의 제한으로 인해 상속이 얼마나 이루어졌는지 알 수 없는 상황에서는 실행 가능한 솔루션이 아니지만 제어된 상황에서는 의도한 대로 작동합니다.

할아버지에게 전화할 수 있습니다.:_이 키워드는 현재 클래스인스턴스를 나타냅니다. 그러나 이 메서드는 다른 컨텍스트에서 보호된 속성 및 현재 인스턴스의 메서드에 액세스할 수 없으며 공용 요소에만 액세스할 수 있습니다. => 모든 업무공식 지원.

// main class that everything inherits
class Grandpa 
{
    public function __construct()
    {
        echo $this->one; // will print 1
        echo $this->two; // error cannot access protected property
    }

}

class Papa extends Grandpa
{
    public function __construct()
    {
        // call Grandpa's constructor
        parent::__construct();
    }
}

class Kiddo extends Papa
{
    public $one = 1;
    protected $two = 2;
    public function __construct()
    {
        Grandpa::__construct();
    }
}

new Kiddo();

php에 대한 재미있는 세부사항: 확장 클래스는 정적인 문제에서 부모 클래스의 비정적 함수를 사용할 수 있습니다.밖에서는 엄밀한 오류를 범하게 됩니다.

error_reporting(E_ALL);

class GrandPa
{
    public function __construct()
    {
        print("construct grandpa<br/>");
        $this->grandPaFkt();
    }

    protected function grandPaFkt(){
        print(">>do Grandpa<br/>");
    }
}

class Pa extends GrandPa
{
    public function __construct()
    {   parent::__construct();
        print("construct Pa <br/>");
    }

    public function paFkt(){
        print(">>do Pa <br>");
    }
}

class Child extends Pa
{
    public function __construct()
    {
        GrandPa::__construct();
        Pa::paFkt();//allright
        //parent::__construct();//whatever you want
        print("construct Child<br/>");
    }

}

$test=new Child();
$test::paFkt();//strict error 

따라서 확장 클래스(자녀) 내에서

parent::paFkt(); 

또는

Pa::paFkt();

부모(또는 grandPa's)(프라이빗이 아닌) 기능에 액세스합니다.

Outside class def

$test::paFkt();

엄밀한 에러가 발생합니다(비정적 기능).

좋아, 또 다른 추악한 해결책:

Papa에서 다음과 같은 함수를 만듭니다.

protected function call2Granpa() {
     return parent::__construct();
}

그럼 꼬맹이에서는 이렇게 쓰죠

parent::call2Granpa();//파파에서 컨스트럭터에게 전화하는 대신.

잘 될 것 같은데...아직 테스트하지 않았기 때문에 오브젝트가 올바르게 작성되어 있는지 잘 모르겠습니다.

나는 이 접근법을 사용했지만 비구축자 함수와 함께 사용했다.

<?php

class grand_pa
{
    public function __construct()
    {
        echo "Hey I am Grand Pa <br>";
    }
}

class pa_pa extends grand_pa
{
    // no need for construct here unless you want to do something specifically within this class as init stuff
    // the construct for this class will be inherited from the parent.
}

class kiddo extends pa_pa
{
    public function __construct()
    {
        parent::__construct();
        echo "Hey I am a child <br>";
    }
}

new kiddo();
?>

물론 pa_pa 구성 내에서 아무것도 할 필요가 없습니다.이를 실행하면 다음과 같이 출력됩니다.

안녕 나는 할아버지야 안녕 나는 아이야

// main class that everything inherits
class Grandpa 
{
    public function __construct()
    {
        $this->___construct();
    }

    protected function ___construct()
    {
        // grandpa's logic
    }

}

class Papa extends Grandpa
{
    public function __construct()
    {
        // call Grandpa's constructor
        parent::__construct();
    }
}

class Kiddo extends Papa
{
    public function __construct()
    {
        parent::___construct();
    }
}

"__construct"는 마법의 이름이 아니라 "doGrandpaStuff"라고 부를 수 있습니다.

    class Grandpa 
{
    public function __construct()
    {
        echo"Hello Kiddo";
    }    
}

class Papa extends Grandpa
{
    public function __construct()
    {            
    }
    public function CallGranddad()
    {
        parent::__construct();
    }
}

class Kiddo extends Papa
{
    public function __construct()
    {

    }
    public function needSomethingFromGrandDad
    {
       parent::CallGranddad();
    }
}

php 7부터 사용할 수 있습니다.

parent::parent::__construct();

언급URL : https://stackoverflow.com/questions/1557608/how-do-i-get-a-php-class-constructor-to-call-its-parents-parents-constructor

반응형