PHP में माता-पिता के तरीकों के साथ तरीकों की घोषणा संगत होनी चाहिए


107
सख्त मानक: चाइल्डक्लास की घोषणा :: customMethod () को पैरेंटक्लास के साथ संगत होना चाहिए: customMethod ())

PHP में इस त्रुटि के संभावित कारण क्या हैं? मुझे इस बारे में जानकारी कहां मिल सकती है कि इसके संगत होने का क्या मतलब है ?


नहीं यह बिल्कुल सही है। @ waiwai933, यदि आप हेडर (सिर्फ पहली पंक्ति:) पोस्ट कर सकते हैं, तो function customMethod( ... )प्रत्येक फ़ंक्शन के लिए हम आपको विशिष्ट समस्या बता सकते हैं
निक

: त्रुटि संदेश और 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)त्रुटि को ट्रिगर किया जाएगा, क्योंकि बच्चे की विधि ने पहले तर्क के लिए एक डिफ़ॉल्ट मान निर्धारित नहीं किया है।
चार्ल्स

1
मेरा मानना ​​है कि दृश्यता वास्तव में एक अलग त्रुटि है। वैसे, मेरी दुकान पर हम सख्त मोड का उपयोग नहीं करते हैं, इस वजह से (हम E_ALL, IIRC का उपयोग करते हैं)।
davidtbernal

12
यह PHP 5.4 में बदल गया है, btw: * E_ALL में शामिल है E_STRICT स्तर त्रुटियों में त्रुटि कॉन्फ़िगरेशन को निष्क्रिय करना। यहां देखें: php.net/manual/en/migration54.other.php
डंकन लॉक

1
&तर्कों में एक एम्परसैंड ( ) गुम होने से यह त्रुटि भी ट्रिगर हो सकती है।
इवानआरएफ

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 () की जाँच करता है जिसके लिए कोई पैरामीटर की आवश्यकता नहीं होती है। हालांकि, $ वर्ग बी की एक वस्तु हो सकती है जिसे एक पैरामीटर की आवश्यकता होती है और इसलिए कॉल रनटाइम में विफल हो जाएगी।

हालांकि यह कभी विफल नहीं हो सकता और त्रुटि को ट्रिगर नहीं करता है

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

स्पष्टीकरण के लिए धन्यवाद, मेरे मामले में आपने जो पहला उदाहरण दिया, वह वही था जो मेरी त्रुटि को ट्रिगर कर रहा था।
बिलिन्हा

इसके लिए धन्यवाद सर।
एल्डोउर

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();
        // ...

    }
}

मैं इन त्रुटियों के आसपास पाने के लिए इस हैक का उपयोग करना पसंद करूंगा। मुझे चिंता है कि इस दृष्टिकोण के लिए कोई जुर्माना हो सकता है? मैं इस पर शोध करूँगा लेकिन यदि आपके पास उस प्रश्न का उत्तर देने में सहायता के लिए कोई संसाधन हैं, तो यह बहुत अच्छा होगा।
एडम फ्रीडमैन

मेरे ख़याल से स्थिति पर निर्भर करता है। अभी भी हाँ यह शायद थोड़ा हैकी है, लेकिन यह php है? पहले से ही, कभी-कभी यह एक अच्छा काम हो सकता है, धन्यवाद! <@
जेम्स जेम्स

आपने मेरा दिन बचाया! यह दर्द के बिना php7 के साथ सर्वर पर विरासत php5 परियोजना को लॉन्च करने का एकमात्र विकल्प था
vladkras

इस मामले के लिए आप डिफ़ॉल्ट मान का उपयोग कर सकते हैं func_get_args(), अर्थात, इन B, इन के public function foo($a = null, $b = null, $c = null)रूप में , यह अनुबंध द्वारा दिए गए अनुबंध को नहीं तोड़ता है A
जेक

1

बस एक इंटरफ़ेस के संदर्भ में इस त्रुटि का विस्तार करने के लिए, यदि आप टाइप कर रहे हैं तो अपने फ़ंक्शन मापदंडों को इस तरह से संकेत दें:

इंटरफ़ेस ए

use Bar;

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

कक्षा बी

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

यदि आप useअपने कार्यान्वयन वर्ग (क्लास बी) पर बयान को शामिल करना भूल गए हैं , तो विधि पैरामीटर समान होने के बावजूद भी आपको यह त्रुटि मिलेगी।


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();
   }
}

इसलिए, मैंने "जो भी" विधि का उपयोग करने की कोशिश की, मैंने "getWhatever" नामक एक नया लिखा। वास्तव में दोनों एक ही कर रहे हैं, बस एक वर्ग लौट रहा है, लेकिन अलग-अलग नामस्थानों के साथ जैसा कि मैंने पहले बताया है।

आशा है कि यह किसी की मदद कर सकता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.