आइए एक दूसरे के लिए उपेक्षा करें कि प्रश्न में विधि क्या है __construct
और इसे कॉल करें frobnicate
। अब मान लीजिए कि आपके पास एक वस्तु api
क्रियान्वयन है IHttpApi
, और एक वस्तु config
क्रियान्वयन IHttpConfig
। स्पष्ट रूप से, यह कोड इंटरफ़ेस को फिट करता है:
$api->frobnicate($config)
लेकिन Upcast हम लगता है जाने api
के लिए IApi
करने के लिए इसे पारित, उदाहरण के लिए function frobnicateTwice(IApi $api)
। अब उस फ़ंक्शन में, frobnicate
कॉल किया जाता है, और चूंकि यह केवल डील करता है IApi
, इसलिए यह एक कॉल कर सकता है जैसे कि $api->frobnicate(new SpecificConfig(...))
जहां SpecificConfig
लागू होता है IConfig
लेकिन नहीं IHttpConfig
। किसी भी बिंदु पर किसी ने भी प्रकार के साथ कुछ भी नहीं किया है, फिर IHttpApi::frobnicate
भी एक SpecificConfig
ऐसा स्थान मिला जहां यह अपेक्षित था IHttpConfig
।
यह अच्छा नहीं है। हम उपद्रव को रोकना नहीं चाहते हैं, हम सबटाइपिंग चाहते हैं, और हम स्पष्ट रूप से एक इंटरफ़ेस को लागू करने वाली कई कक्षाएं चाहते हैं। तो एकमात्र समझदार विकल्प एक उपप्रकार विधि को रोकना है जो मापदंडों के लिए अधिक विशिष्ट प्रकार की आवश्यकता होती है । (एक समान समस्या तब होती है जब आप अधिक सामान्य प्रकार वापस करना चाहते हैं ।)
औपचारिक रूप से, आप बहुरूपता, विचरण के आसपास के एक क्लासिक जाल में चले गए हैं । एक प्रकार की सभी घटनाओं को T
उपप्रकार द्वारा प्रतिस्थापित नहीं किया जा सकता है U
। इसके विपरीत, एक प्रकार की सभी घटनाओं को सुपरपाइपT
द्वारा प्रतिस्थापित नहीं किया जा सकता है । सावधानीपूर्वक विचार (या बेहतर अभी तक, प्रकार के सिद्धांत का सख्त अनुप्रयोग) आवश्यक है। S
वापस आ रहा है __construct
: AFAIK के बाद से आप वास्तव में एक इंटरफ़ेस लागू नहीं कर सकते, केवल एक ठोस कार्यान्वयनकर्ता, यह एक व्यर्थ प्रतिबंध की तरह लग सकता है (यह कभी भी इंटरफ़ेस के माध्यम से कॉल नहीं किया जाएगा)। लेकिन उस मामले __construct
में, इंटरफ़ेस में शामिल क्यों करना शुरू करने के लिए? बावजूद, __construct
यहां विशेष-मामले में इसका उपयोग बहुत कम होगा ।