यह एक लंबी, दुखद कहानी है।
जब PHP 5.2 ने पहली बार इस चेतावनी को पेश किया, तो देर से स्थिर बाइंडिंग भाषा में नहीं थे। यदि आप देर से स्थैतिक बाइंडिंग से परिचित नहीं हैं, तो ध्यान दें कि कोड इस तरह से काम नहीं करता है जिस तरह से आप उम्मीद कर सकते हैं:
<?php
abstract class ParentClass {
static function foo() {
echo "I'm gonna do bar()";
self::bar();
}
abstract static function bar();
}
class ChildClass extends ParentClass {
static function bar() {
echo "Hello, World!";
}
}
ChildClass::foo();
सख्त मोड की चेतावनी को छोड़कर, ऊपर दिया गया कोड काम नहीं करता है। self::bar()
में कॉल foo()
स्पष्ट रूप को दर्शाता है bar()
की विधि ParentClass
, तब भी जब foo()
की विधि के रूप में कहा जाता है ChildClass
। यदि आप इस कोड को सख्त मोड से चलाने का प्रयास करते हैं, तो आपको " PHP घातक त्रुटि: सार पद्धति को कॉल नहीं किया जा सकता है ।
इसे देखते हुए, PHP 5.2 में सार स्थिर तरीके बेकार थे। अमूर्त पद्धति का उपयोग करने का पूरा बिंदु यह है कि आप कोड लिख सकते हैं जो विधि को कॉल करता है, यह जाने बिना कि यह किस कार्यान्वयन के लिए बुला रहा है - और फिर विभिन्न बच्चे वर्गों पर अलग-अलग कार्यान्वयन प्रदान करते हैं। लेकिन चूंकि PHP 5.2 में पैरेंट क्लास का एक तरीका लिखने के लिए कोई साफ तरीका नहीं है जो कि चाइल्ड क्लास के स्टैटिक मेथड को कॉल करता है, जिस पर इसे कॉल किया जाता है, एब्सट्रैक्ट स्टैटिक मेथड का यह प्रयोग संभव नहीं है। इसलिए abstract static
PHP 5.2 का कोई भी उपयोग खराब कोड है, शायद यह गलतफहमी से प्रेरित है कि self
कीवर्ड कैसे काम करता है। इस पर चेतावनी फेंकना पूरी तरह से उचित था।
लेकिन तब PHP 5.3 उस वर्ग को संदर्भित करने की क्षमता में जोड़ा गया जिस पर एक विधि को static
कीवर्ड के माध्यम से बुलाया गया था (कीवर्ड के विपरीत self
, जो हमेशा उस वर्ग को संदर्भित करता है जिसमें विधि को परिभाषित किया गया था )। आप को बदलते हैं self::bar()
करने के लिए static::bar()
ऊपर मेरी उदाहरण में, यह पीएचपी 5.3 में और ऊपर ठीक काम करता है। आप के बारे में अधिक पढ़ सकते हैं self
बनाम static
पर नए आत्म बनाम नई स्थिर ।
स्थैतिक कीवर्ड के साथ, abstract static
चेतावनी फेंकने के लिए स्पष्ट तर्क चला गया था। देर से स्थिर बाइंडिंग का मुख्य उद्देश्य माता-पिता वर्ग में परिभाषित विधियों को स्थिर तरीकों को कॉल करने की अनुमति देना था जो कि बाल कक्षाओं में परिभाषित किए जाएंगे; अमूर्त स्थिर विधियों को अनुमति देना उचित और सुसंगत लगता है जिससे अस्तित्व में देर से स्थैतिक बाइंडिंग मिलती है।
आप अभी भी, मुझे लगता है, चेतावनी रखने के लिए एक मामला बना सकते हैं। उदाहरण के लिए, आप तर्क दे सकता है (बदल कर यह तय करने के बाद भी कि जब पीएचपी की मदद से आप अमूर्त वर्ग के स्थिर तरीकों कहते हैं, ऊपर मेरे उदाहरण में self
साथ static
आप एक सार्वजनिक विधि उजागर कर रहे हैं) ParentClass::foo()
जो है टूट और आप नहीं है वास्तव में चाहते हैं कि बेनकाब। एक गैर-स्थैतिक वर्ग का उपयोग करना - अर्थात, सभी तरीकों को उदाहरण के तरीके बनाना और ParentClass
सभी के बच्चों को एकल या कुछ और बनाना - इस समस्या को हल करेगा, क्योंकि ParentClass
, सार होने के नाते, तुरंत नहीं किया जा सकता है और इसलिए इसकी आवृत्ति के तरीके नहीं हो सकते हैं बुलाया जाए। मुझे लगता है कि यह तर्क कमजोर है (क्योंकि मुझे लगता है कि उजागर करनाParentClass::foo()
एक बड़ी बात नहीं है और स्थिर वर्गों के बजाय एकल का उपयोग करना अक्सर अनावश्यक रूप से क्रिया और बदसूरत होता है), लेकिन आप यथोचित असहमत हो सकते हैं - यह कुछ व्यक्तिपरक कॉल है।
तो इस तर्क के आधार पर, PHP देवों ने भाषा में चेतावनी को सही रखा है?
उह, बिल्कुल नहीं ।
PHP बग रिपोर्ट 53081, ऊपर लिंक, static::foo()
निर्माण के अलावा के बाद से गिराए जाने की चेतावनी के लिए बुलाया गया था, जो अमूर्त स्थिर तरीकों को उचित और उपयोगी बना दिया था। रासमस लेरडोर्फ (PHP का निर्माता) अनुरोध को फर्जी करार देकर शुरू होता है और चेतावनी को सही ठहराने की कोशिश के लिए खराब तर्क की लंबी श्रृंखला से गुजरता है। फिर, आखिरकार, यह विनिमय होता है:
जियोर्जियो
मुझे पता है पर:
abstract class cA
{
//static function A(){self::B();} error, undefined method
static function A(){static::B();} // good
abstract static function B();
}
class cB extends cA
{
static function B(){echo "ok";}
}
cB::A();
Rasmus
ठीक है, यह ठीक है कि यह कैसे काम करना चाहिए।
जियोर्जियो
लेकिन इसकी अनुमति नहीं है :(
Rasmus
क्या अनुमति नहीं है?
abstract class cA {
static function A(){static::B();}
abstract static function B();
}
class cB extends cA {
static function B(){echo "ok";}
}
cB::A();
यह ठीक काम करता है। आप स्पष्ट रूप से स्वयं :: बी () नहीं कह सकते, लेकिन स्थिर :: बी () ठीक है।
रासमस द्वारा दावा किया गया कि उसके उदाहरण में कोड "ठीक काम करता है" झूठा है; जैसा कि आप जानते हैं, यह एक सख्त मोड चेतावनी फेंकता है। मुझे लगता है कि वह सख्त मोड के बिना परीक्षण कर रहा था। बावजूद, एक भ्रमित रासमस ने अनुरोध को गलत तरीके से "फर्जी" के रूप में बंद कर दिया।
और इसीलिए यह चेतावनी अभी भी भाषा में है। यह पूरी तरह से संतोषजनक स्पष्टीकरण नहीं हो सकता है - आप शायद यहाँ आये थे उम्मीद है कि चेतावनी का तर्कसंगत औचित्य था। दुर्भाग्य से, वास्तविक दुनिया में, कभी-कभी विकल्प तर्कसंगत निर्णय लेने के बजाय सांसारिक गलतियों और बुरे तर्क से पैदा होते हैं। यह बस उन समयों में से एक है।
सौभाग्य से, आकलन योग्य निकिता पोपोव ने PHP 7 में PHP RFC के भाग के रूप में भाषा से चेतावनी को हटा दिया है : E_STRICT नोटिस को फिर से देखें । अंततः, पवित्रता प्रबल हो गई है, और PHP 7 जारी होने के बाद हम सभी abstract static
इस मूर्खतापूर्ण चेतावनी को प्राप्त किए बिना खुशी से उपयोग कर सकते हैं ।