5.4.0 संस्करण के साथ शुरू, PHP में एक नया भाषा निर्माण दिखाई देगा -
लक्षण , जो एक मिश्रण (
मिश्रण में ) का उपयोग करने की संभावना को लागू करता है। अशुद्धता तंत्र कोड के पुन: उपयोग का एक अन्य तंत्र है और एक रूप में या किसी अन्य भाषा में मौजूद है, उदाहरण के लिए, रूबी, पायथन, कॉमन लिस्प, आदि।
बहुसंख्यक विरासत की समस्याओं से बचने के साथ वर्ग व्यवहार को लागू करते समय असमानताएं आपको मौजूदा कोड का उपयोग करने की अनुमति देती हैं। अलग-अलग सॉफ्टवेयर लाइब्रेरी में संयुक्त रूप से एक-दूसरे के साथ संपर्क करने वाली अशुद्धताएं, जटिल तर्क के कार्यान्वयन में एक बहुत शक्तिशाली उपकरण हैं।
यह ध्यान दिया जाना चाहिए कि PHP में अशुद्धता कार्यान्वयन
कम से कम 4.0.1 संस्करण के
बाद से मौजूद है, और वर्तमान में मौजूद हैं, सबसे अधिक बार नाम व्यवहार के तहत, लोकप्रिय फ्रेमवर्क की एक संख्या में, उदाहरण के लिए, Yii, Symfony, Doctrine, CakePhp, Propel में।
आलेख का उद्देश्य केवल 5.4.0 संस्करण से पहले PHP में अशुद्धियों को लागू करने के लिए कई बुनियादी तरीकों का प्रदर्शन और तुलना करना है, केवल भाषा के कार्यों के आधार पर और तीसरे पक्ष के एक्सटेंशन का उपयोग नहीं करना, जैसे कि, उदाहरण के लिए, PECL रनकिट से
runkit_method_code फ़ंक्शन।
तुलना करते समय, निम्न मानदंडों का उपयोग किया जाएगा:
- मिक्सिंग रिजल्ट में ऑब्जेक्ट की तरह ही होता है
- क्या एक अशुद्धता दूसरे के साथ बातचीत कर सकती है
- क्या यह सत्यापित करना संभव है कि मिश्रण के परिणाम में एक या दूसरी अशुद्धता है
- क्या एक मनमाना वर्ग के लिए एक मिश्रण जोड़ना संभव है
- क्या पहले से बनाई गई वस्तु "मक्खी पर" के लिए एक मिश्रण जोड़ना संभव है
- कार्यान्वयन कितना सरल है
विधि एक: जादू के तरीके
यह विधि मैजिक विधियों
__call ,
__get और अन्य का उपयोग करने के विचार पर आधारित है: अशुद्धियों का एक संग्रह मिश्रण परिणाम में जोड़ा जाता है, और जादू विधियों के कार्यान्वयन से वांछित अशुद्धता का चयन होता है। प्रत्येक अशुद्धता को परिणाम के संदर्भ में परिमाणित किया जा सकता है, इस प्रकार एक दूसरे के साथ अशुद्धियों के संपर्क का समर्थन किया जाता है।
कार्यान्वयन उदाहरण:
abstract class Mixin { protected $mixedObject = null; public function setObject( MixedObject $object ) { $this->mixedObject = $object; } abstract public function getName(); } class MixedObject { private $mixins = array(); public function addMixin( Mixin $mixin ) { $mixin->setObject( $this ); $this->mixins[$mixin->getName()] = $mixin; } public function hasMixin( $mixinName ) { return array_key_exists( $mixinName, $this->mixins ); } public function __call( $name, $arguments ) { foreach ($this->mixins as $mixin) { if (is_callable( array( $mixin, $name ) )) { return call_user_func_array( array( $mixin, $name ), $arguments ); } } throw new \Exception('Unknown method call.'); } }
उपयोग उदाहरण:
class Foo extends MixedObject { public function objectFunc() { return 'FooName'; } } class Debuggable extends Mixin { public function getName() { return 'Debug'; } public function getDebug() { return sprintf( "%s", $this->mixedObject->objectFunc() ); } } class Loggable extends Mixin { public function getName() { return 'Log'; } public function getLog( $level ) { return $this->mixedObject->hasMixin( 'Debug' ) ? sprintf( "%s %s", $level, $this->mixedObject->getDebug() ) : sprintf( "%s", $level ); } } $foo = new Foo(); $foo->addMixin( new Debuggable() ); $foo->addMixin( new Loggable() ); print $foo->getDebug(); print $foo->getLog( 'info' );
जाहिर है, परिणाम उसी प्रकार का होता है जैसे कि वस्तु। इसके अलावा, यह दृष्टिकोण दोनों को वस्तु के साथ और एक-दूसरे के साथ लिंक
$ $ का उपयोग करके संचारित करने में सक्षम अशुद्धियों को छोड़ देता
है- मिश्रित मिश्रित और अद्वितीय नाम प्रणाली।
पेशेवरों और विपक्ष:
- [+] समाधान पारदर्शी और स्पष्ट है
- [+] आप पहले से ही बनाई गई वस्तु में एक मिश्रण जोड़ सकते हैं, आप पहले से उपयोग किए गए नाम के साथ भी कर सकते हैं
- [-] परिणाम को मिश्रितऑब्जेक्ट क्लास से विरासत में लिया जाना चाहिए, इसलिए, मिश्रण का उपयोग करने के लिए, एक प्रकार का पदानुक्रम आवंटित किया जाना चाहिए
- [-] अशुद्धियों के नाम की विशिष्टता के लिए स्थिति पर निरंतर ध्यान देने की आवश्यकता है, और यहाँ, शायद, कुछ सम्मेलनों को पेश करना उपयोगी होगा
विधि दो: वस्तु संदर्भ
यह विधि
$ इस चर की कुछ विशेषता पर आधारित है। अर्थात्:
$ यह कॉलिंग ऑब्जेक्ट का संदर्भ है (आमतौर पर वह वस्तु जिसके लिए विधि होती है, लेकिन संभवतः दूसरी वस्तु, यदि विधि को द्वितीयक वस्तु के संदर्भ से वैधानिक रूप से कहा जाता है )।
हाइलाइट किए गए शब्द इस तरह के कार्यान्वयन को सक्षम करते हैं:
class Foo { public function objectFunc() { return 'FooName'; } } class Debuggable { public function getDebug() { return sprintf( "%s", $this->objectFunc() ); } } class Loggable { public function getLog( $level ) { return is_callable( array( $this, 'getDebug' ) ) ? sprintf( "%s %s", $level, $this->getDebug() ) : sprintf( "%s", $level ); } }
... और उपयोग करता है:
class MixedFoo extends Foo { public function getDebug() { return Debuggable::getDebug(); } public function getLog() { return Loggable::getLog( func_get_arg( 0 ) ); } } $foo = new MixedFoo(); $foo->getDebug(); $foo->getLog( 'info' );
इसके अलावा,
मिक्सफू वर्ग के कोड की पीढ़ी को स्वचालित करना आसान है, बाद में
निष्कासित , उत्पन्न वर्ग की एक वस्तु का निर्माण और इसकी वापसी, जिसके परिणामस्वरूप लगभग निम्नलिखित हैं:
$foo = Mixer::Construct( 'Foo', array( 'Debuggable', 'Loggable' ) ); $foo->getDebug(); $foo->getLog( 'info' );
प्रत्येक अशुद्धता के लिए एक अलग इंटरफ़ेस बनाना और सूची में उत्पन्न वर्ग के लिए
कार्यान्वयन को जोड़ना भी संभव है।
interface IMixinDebuggable { public function getDebug(); } ... $foo = Mixer::Construct( 'Foo', array( 'IMixinDebuggable' => 'Debuggable', 'Loggable' ) );
यह संभव है, क्योंकि मिश्रण परिणाम इन इंटरफेस को लागू करेगा, और एक अशुद्धता के अस्तित्व के लिए जाँच फिर एक मूल
इंस्टेंस कॉल के
लिए कम हो जाएगा:
class Loggable { public function getLog( $level ) { return $this instanceof IMixinDebuggable ? sprintf( "%s %s", $level, $this->getDebug() ) : sprintf( "%s", $level ); } }
पेशेवरों और विपक्ष:
- [+] किसी एक्स्टेंसिबल ऑब्जेक्ट को इनहेरिट करने की कोई आवश्यकता नहीं है, इसलिए आप किसी भी वर्ग में किसी भी अशुद्धियों को मिला सकते हैं
- [+] पहली विधि के विपरीत, "मिश्रित" तरीके सीधे परिणाम के रूप में लागू किए जाते हैं, इसलिए आपको संग्रह से अधिक समय व्यतीत नहीं करना पड़ेगा, और कोड थोड़ा और तेजी से काम करेगा
- [-] एक मनमानी वर्ग की पहले से निर्मित वस्तु के विस्तार का कोई तरीका नहीं है
- [-] कोड पीढ़ी बेकार है
निष्कर्ष
दोनों विधियां आपको कक्षाओं के व्यवहार को गतिशील रूप से परिष्कृत करने की अनुमति देती हैं, उन्हें मौजूदा कार्यान्वयन के साथ पूरक करती हैं, और उपयोग करने का अधिकार है।
यदि आप परिणाम एक अलग तालिका में रखते हैं:
| जादू के तरीके | वस्तु प्रसंग |
---|
मिक्सिंग रिजल्ट में ऑब्जेक्ट की तरह ही टाइप होता है | हां | हां |
क्या एक अशुद्धता दूसरे के साथ बातचीत कर सकती है | हां | हां |
क्या यह सत्यापित करना संभव है कि मिश्रण परिणाम में एक या कोई अन्य अशुद्धता है | हां | हां |
क्या एक मनमाना वर्ग में प्रवेश जोड़ना संभव है | नहीं | हां |
क्या पहले से बनाई गई वस्तु "मक्खी पर" के लिए एक मिश्रण जोड़ना संभव है | हां | नहीं |
कार्यान्वयन कितना सरल है | सरल और स्पष्ट | कोड पीढ़ी के साथ जुड़े |
यह नोटिस करना मुश्किल नहीं है कि पहली विधि के नुकसान दूसरे द्वारा हल किए गए हैं, साथ ही साथ इसके विपरीत, और इस या उस पद्धति के दायरे के बारे में एक निष्कर्ष निकालना भी है।
पहली परियोजना के डिजाइन का हिस्सा है, और इसलिए इसका दायरा जटिल व्यावसायिक वस्तुओं के निर्माण का कार्य है।
दूसरा आपको अलग-अलग स्वतंत्र पुस्तकालयों में अशुद्धियों को अलग करने और किसी भी परियोजनाओं में उनका उपयोग करने की अनुमति देता है, इसलिए इसका दायरा आपके कई परियोजनाओं के लिए हल्के कार्य है।
आपका धन्यवाद