메서드 선언은 PHP의 부모 메서드와 호환되어야합니다.


107
엄격한 표준 : childClass :: customMethod () 선언은 parentClass :: customMethod () 선언과 호환되어야합니다.

PHP에서이 오류의 가능한 원인은 무엇입니까? 호환성의 의미에 대한 정보는 어디에서 찾을 수 있습니까 ?


notJim이 정확히 맞습니다. 당신은 (단지 첫 번째 줄 : 헤더를 게시 할 수 있다면 @ waiwai933는 function customMethod( ... )) 각 기능을 우리는 당신에게 특정 문제를 말할 수
nickf

오류 메시지 및 PHP 컴파일 시간에 대한 자세한 내용 : bugs.php.net/bug.php?id=46851
hakre


1
내 문제는 인수가 유형 힌트되었지만 use Closure;클래스 맨 위에 추가되지 않았다는 것입니다 (유형 힌트가 이었기 때문에 Closure). 따라서 ... 그런 종속성이 누락되었는지 확인하십시오.
라이언

답변:


126

childClass::customMethod()인수가 다르거 나 액세스 수준 (공개 / 개인 / 보호)이 parentClass::customMethod().


1
아마 그것 때문에 가시성 , 방법 서명이 PHP에서 문제가되지 않습니다
가브리엘 소사

43
동일한 정확한 인수 기본값을 갖는 것도 중요합니다. 예를 들어, parentClass::customMethod($thing = false)childClass::customMethod($thing)아이의 방법은 첫 번째 인수에 대한 기본 값을 정의하지 않았기 때문에 오류를 발생하게됩니다.
Charles

1
가시성은 실제로 다른 오류라고 생각합니다. 그런데 저희 가게에서는 Strict 모드를 사용하지 않습니다. (E_ALL, IIRC 사용).
davidtbernal

12
이것은 PHP 5.4, btw에서 변경되었습니다. * E_ALL은 이제 error_reporting 구성 지시문에 E_STRICT 수준 오류를 포함합니다. 여기를 참조하십시오 : php.net/manual/en/migration54.other.php
던컨 잠금

1
&인수에 앰퍼샌드 ( )가 없으면이 오류도 트리거 될 수 있습니다.
IvanRF

36

이 메시지는 런타임에 실패 할 수있는 특정 가능한 메소드 호출이 있음을 의미합니다. 당신이 가지고 있다고 가정

class A { public function foo($a = 1) {;}}
class B extends A { public function foo($a) {;}}
function bar(A $a) {$a->foo();}

컴파일러는 매개 변수가 필요없는 A :: foo ()의 요구 사항에 대해 $ a-> foo () 호출 만 확인합니다. 그러나 $ a는 매개 변수가 필요한 클래스 B의 객체 일 수 있으므로 런타임에 호출이 실패합니다.

그러나 이것은 결코 실패 할 수 없으며 오류를 유발하지 않습니다.

class A { public function foo($a) {;}}
class B extends A { public function foo($a = 1) {;}}
function bar(A $a) {$a->foo();}

따라서 어떤 메소드도 상위 메소드보다 더 많은 필수 매개 변수를 가질 수 없습니다.

유형 힌트가 일치하지 않는 경우에도 동일한 메시지가 생성되지만이 경우 PHP는 훨씬 더 제한적입니다. 이것은 오류를 제공합니다.

class A { public function foo(StdClass $a) {;}}
class B extends A { public function foo($a) {;}}

이렇게 :

class A { public function foo($a) {;}}
class B extends A { public function foo(StdClass $a) {;}}

그것은 필요한 것보다 더 제한적인 것처럼 보이며 내부 때문이라고 생각합니다.

가시성 차이로 인해 다른 오류가 발생하지만 기본적인 이유는 동일합니다. 부모 메서드보다 덜 눈에 띄는 메서드는 없습니다.


2
마지막 예에서-합법적이므로 여기에 오류가 있어서는 안됩니다. stdClass $ a는 혼합 $ a보다 제한적입니다. 이 문제를 해결할 방법이 있습니까? 내 말은이 경우 PHP는 이것을 허용해야하지만 여전히 오류가 발생합니다 ...
galchen

2
마지막 예제는 형식에 안전하므로 "필요한 것보다 더 제한적"입니다. 이것은 C ++ 및 Java의 다형성과 충돌하기 때문에화물 컬트 프로그래밍의 경우 일 수 있습니다. en.wikipedia.org/wiki/…
Warbo

설명해 주셔서 감사합니다. 제 경우 첫 번째 예는 정확히 내 오류를 유발 한 것입니다.
billynoah

감사합니다.
Eldoïr

22

오류를 끄지 않고 OOP 양식을 유지하려면 다음을 수행 할 수도 있습니다.

class A
{
    public function foo() {
        ;
    }
}
class B extends A
{
    /*instead of : 
    public function foo($a, $b, $c) {*/
    public function foo() {
        list($a, $b, $c) = func_get_args();
        // ...

    }
}

이 해킹을 사용하여 이러한 오류를 피하고 싶습니다. 이 접근 방식에 성능 저하가있을 수 있다고 걱정합니까? 나는 이것을 조사 할 것이지만 그 질문에 답하는 데 도움이 될 자원이 있다면 좋을 것입니다.
Adam Friedman

내가 생각하는 상황에 따라 다릅니다. 그래도 예, 약간 해 키일 수 있지만 PHP입니까? 이미, 때로는 좋은 해결 방법이 될 수 있습니다. 감사합니다! <@
Master James

당신은 내 하루를 구했습니다! 이 고통없이 php7와 서버 출시 레거시 PHP5 프로젝트에 유일한 선택이었다
vladkras

이 경우를 들어 대신의 디폴트 값을 사용할 수 있습니다 func_get_args()즉,에서, B, public function foo($a = null, $b = null, $c = null),이 아프게하지 않는 한 계약이 약속을 A.
Jake

1

다음과 같이 함수 매개 변수에 힌트를 입력하는 경우 인터페이스 컨텍스트에서이 오류를 확장하면됩니다.

인터페이스 A

use Bar;

interface A
{
    public function foo(Bar $b);
}

클래스 B

class B implements A
{
    public function foo(Bar $b);
}

use구현 클래스 (Class B)에 문 을 포함하는 것을 잊은 경우 메서드 매개 변수가 동일하더라도이 오류가 발생합니다.


0

GitHub에서 기존 클래스를 확장하는 동안이 문제에 직면했습니다. 나는 내 자신을 설명하려고 노력할 것입니다. 먼저 내가 그래야만하는 것처럼 수업을 작성하고, 그리고 나서 지금있는 수업을 작성합니다.

그래도

namespace mycompany\CutreApi;

use mycompany\CutreApi\ClassOfVendor;

class CutreApi extends \vendor\AwesomeApi\AwesomeApi
{
   public function whatever(): ClassOfVendor
   {
        return new ClassOfVendor();
   }
}

내가 마침내 한 일

namespace mycompany\CutreApi;

use \vendor\AwesomeApi\ClassOfVendor;

class CutreApi extends \vendor\AwesomeApi\AwesomeApi
{
   public function whatever(): ClassOfVendor
   {
        return new \mycompany\CutreApi\ClassOfVendor();
   }
}

따라서 네임 스페이스가있는 클래스를 반환하는 메서드를 사용하고 동일한 클래스를 반환하지만 다른 네임 스페이스를 사용하여 반환하려고 할 때도이 오류가 발생하는 것 같습니다. 다행히도이 솔루션을 찾았지만 PHP 7.2에서이 기능의 이점을 완전히 이해하지 못합니다. 입력 매개 변수의 재정의 및 / 또는 방법.

이전 aproach의 한 가지 단점은 IDE가 \ mycompany \ CutreApi \ ClassOfVendor ()에 구현 된 새 메서드를 인식 할 수 없다는 것입니다. 따라서 지금은이 구현을 사용하겠습니다.

현재 완료

namespace mycompany\CutreApi;

use mycompany\CutreApi\ClassOfVendor;

class CutreApi extends \vendor\AwesomeApi\AwesomeApi
{
   public function getWhatever(): ClassOfVendor
   {
        return new ClassOfVendor();
   }
}

그래서 "whatever"메소드를 사용하는 대신 "getWhatever"라는 새 메소드를 작성했습니다. 사실 둘 다 똑같은 일을하면서 클래스를 반환하지만 앞서 설명한 것처럼 다른 네임 스페이스를 사용합니다.

이것이 누군가를 도울 수 있기를 바랍니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.