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
'it-source' 카테고리의 다른 글
Python에 디렉토리가 있는지 어떻게 확인하나요? (0) | 2023.02.02 |
---|---|
제한 글로벌 없음 (0) | 2023.02.02 |
JavaScript에서 "function*"란 무엇입니까? (0) | 2023.02.02 |
SSL/TLS 보호를 위해 openssl 확장이 필요합니다. (0) | 2023.02.02 |
작곡가에게 포크를 어떻게 요구합니까? (0) | 2023.02.02 |