PHP의 특성 내에서 클래스 생성자를 오버로드하는 방법 >= 5.4
PHP 5에서는 컨스트럭터(및 기타 메서드)를 오버로드할 수 있습니다.하지만 다음과 같은 코드가 나타나면:
class Base {
public function __construct($a, $b) {
echo $a+$b;
}
public function sayHello() {
echo 'Hello ';
}
}
trait SayWorld {
public function __construct($a, $b, $c = 0) {
echo (int)$c * ($a+$b);
}
public function sayHello($a = null) {
parent::sayHello();
echo 'World!'.$a;
}
}
class MyHelloWorld extends Base {
use SayWorld;
}
$o = new MyHelloWorld(2, 3);
$o->sayHello(1);
오류가 발생했습니다.
치명적인 오류: MyHelloWorld에 특성에서 가져온 충돌 생성자 정의가 있습니다.
어떻게 하면 고칠 수 있을까요?여기서 내 코드를 테스트할 수 있습니다.
지금으로서는 당신이 원하는 것을 할 수 있는 유일한 방법이라고 생각합니다.
class MyHelloWorld extends Base {
use SayWorld {
SayWorld::__construct as private __swConstruct;
}
public function __construct($a, $b, $c = 0)
{
$this->__swConstruct($a, $b, $c);
}
}
편집 2:
1년 이상 PHP의 특성을 다루어 온 제 조언은, 특성으로 컨스트럭터를 쓰는 것을 전혀 피하거나, 필요하다면 파라미터가 없는 것으로 하는 것입니다.이러한 특성을 갖는 것은 일반적으로 컨스트럭터의 개념에 반하는 것입니다.즉, 컨스트럭터는 자신이 속한 클래스에 특정되어야 합니다.다른 고급 언어는 암묵적인 생성자 상속을 지원하지 않습니다.이는 생성자가 다른 메서드보다 클래스에 훨씬 더 강한 관계를 가지고 있기 때문입니다.사실 그들은 LSP조차 적용되지 않을 정도로 강한 관계를 맺고 있다.Scala 언어(Java의 매우 성숙하고 SOLID 친화적인 후속 버전)의 특성은 매개 변수를 가진 컨스트럭터를 가질 수 없습니다.
편집 1:
PHP 5.4.11에는 실제로 슈퍼클래스 메서드에 에일리어스를 붙일 수 있는 버그가 있습니다.그러나 PHP 개발자들은 이를 '아니오'라고 여겼기 때문에 위에서 제시한 번거로운 해결책으로는 여전히 어려움을 겪고 있습니다.그러나 이 버그로 인해 이 문제를 해결할 수 있는 방법이 논의되고 있으며, 향후 출시에서는 이 버그가 대상이 될 것으로 기대하고 있습니다.
그러는 동안 나는 같은 문제를 몇 번이나 만났다.특성을 사용하기 위해 여러 번 반복해야 하는 파라미터와 docblock 행의 수에 따라 나의 짜증이 기하급수적으로 증가했다.그래서 가능한 한 DRY 규칙을 고수하기 위해 다음과 같은 패턴을 생각해 냈습니다.
다음과 같이 파라미터 세트 전체를 반복하는 대신 다음과 같이 하십시오.
trait SayWorld {
/**
* This is a valid docblock.
*
* @param int $a Doc comment.
* @param int $b Doc comment.
*/
public function __construct($a, $b) {
echo (int)$c * ($a+$b);
}
}
class MyHelloWorld extends Base {
use SayWorld {
SayWorld::__construct as private __swConstruct;
}
/**
* Repeated and unnecessary docblock.
*
* @param int $a Doc comment.
* @param int $b Doc comment.
* @param int $c Doc comment.
*/
public function __construct($a, $b, $c = 0)
{
$this->__swConstruct($a, $b);
}
}
저는 Tuple(C#과 Python 사용자에게 익숙한 개념)과 비슷한 클래스를 작성하여 끝없는 파라미터 목록 대신 사용합니다.
class SayWorldConstructTuple
{
public $a;
public $b;
public function __construct($a, $b)
{
$this->a = $a;
$this->b = $b;
}
}
class MyHelloWorld extends Base {
use SayWorld {
SayWorld::__construct as private __swConstruct;
}
/**
* New and valid docblock.
*
* @param SayWorldConstructTuple $Tuple
* @param int $c Additional parameter.
*/
public function __construct(SayWorldConstructTuple $Tuple, $c = 0)
{
$this->__swConstruct($Tuple->a, $Tuple->b);
$this->c = $c;
}
}
주의: 이 패턴은 많은 양의 태플 생성자 매개 변수와 태플을 사용하는 더 많은 클래스에서 더 유용합니다.
PHP의 동적 특성을 사용하여 더욱 자동화할 수 있습니다.
시험:
use SayWorld {
Base::__construct insteadof SayWorld;
}
참조: PHP 문서
오래된 포스트지만, 이 포스트가 도움이 되는 경우:
저도 비슷한 상황이었지만 조금 다른 접근법을 쓰기로 했습니다.WordPress 플러그인을 쓰고 있었는데 플러그인 정보(버전, 이름, 텍스트 도메인 등)를 전달하고 싶었지만 리팩터링이나 다른 클래스 확장을 할 때 각 파일을 변경하는 것이 싫었기 때문에 클래스 고유의 조작을 위해 단순히 초기화 함수를 호출하는 컨스트럭터로 특성을 만들었습니다.
trait HasPluginInfoTrait{
public function __construct() {
$this->plugin_name = PLUGIN_NAME;
$this->version = PLUGIN_VERSION;
if ( method_exists( $this, 'init' ){
$this->init();
}
}
}
class SampleClass {
use HasPluginInfoTrait;
private function init(){
// Code specific to SampleClass
}
}
언급URL : https://stackoverflow.com/questions/12478124/how-to-overload-class-constructor-within-traits-in-php-5-4
'programing' 카테고리의 다른 글
오브젝트 속성을 반복합니다. (0) | 2022.09.06 |
---|---|
C++의 제한은 C언어와 비교했을 때 어떻게 됩니까? (0) | 2022.09.05 |
VueJs 콧수염 데이터 바인딩이 작동하지 않습니다.디버깅하려면 어떻게 해야 하나요? (0) | 2022.09.05 |
옵션을 사용하여 명령줄에서 .sql 파일을 내보내고 가져오려면 어떻게 해야 합니까? (0) | 2022.09.05 |
UTC 날짜 시간을 로컬 날짜 시간으로 변환 (0) | 2022.09.05 |