जाँच रहा है कि क्या एक इंस्टा की क्लास एक इंटरफ़ेस लागू करती है?


148

एक वर्ग उदाहरण को देखते हुए, क्या यह निर्धारित करना संभव है कि क्या यह किसी विशेष इंटरफ़ेस को लागू करता है? जहाँ तक मुझे पता है, सीधे-सीधे ऐसा करने के लिए कोई अंतर्निहित कार्य नहीं है। मेरे पास क्या विकल्प हैं (यदि कोई हो)?

जवाबों:


258
interface IInterface
{
}

class TheClass implements IInterface
{
}

$cls = new TheClass();
if ($cls instanceof IInterface) {
    echo "yes";
}

आप "इंस्टोफ़" ऑपरेटर का उपयोग कर सकते हैं। इसका उपयोग करने के लिए, बाएं ऑपरेंड एक वर्ग उदाहरण है और सही ऑपरेंड एक इंटरफ़ेस है। यदि ऑब्जेक्ट किसी विशेष इंटरफ़ेस को लागू करता है तो यह सही है।


102

के रूप में therefromhere बताते हैं, आप उपयोग कर सकते हैं class_implements()। परावर्तन के साथ के रूप में, यह आपको एक स्ट्रिंग के रूप में वर्ग का नाम निर्दिष्ट करने की अनुमति देता है और इसके लिए कक्षा के उदाहरण की आवश्यकता नहीं होती है:

interface IInterface
{
}

class TheClass implements IInterface
{
}

$interfaces = class_implements('TheClass');

if (isset($interfaces['IInterface'])) {
    echo "Yes!";
}

class_implements() एसपीएल विस्तार का हिस्सा है।

देखें: http://php.net/manual/en/function.class-implements.php

प्रदर्शन जांच

कुछ सरल प्रदर्शन परीक्षण प्रत्येक दृष्टिकोण की लागत को दर्शाते हैं:

किसी वस्तु के उदाहरण को देखते हुए

लूप के बाहर ऑब्जेक्ट निर्माण (100,000 पुनरावृत्तियों)
 ____________________________________________
| class_implements | परावर्तन | instOf |
| ------------------ | ------------ | ------------ |
| 140 एमएस | 290 एमएस | 35 एमएस |
'--------------------------------------------'

लूप के अंदर वस्तु निर्माण (100,000 पुनरावृत्तियों)
 ____________________________________________
| class_implements | परावर्तन | instOf |
| ------------------ | ------------ | ------------ |
| 182 एमएस | 340 एमएस | 83 एमएस | सस्ता कंस्ट्रक्टर
| 431 एमएस | 607 एमएस | 338 एमएस | महँगा कंस्ट्रक्टर
'--------------------------------------------'

केवल एक वर्ग का नाम दिया

100,000 पुनरावृत्तियों
 ____________________________________________
| class_implements | परावर्तन | instOf |
| ------------------ | ------------ | ------------ |
| 149 एमएस | 295 एमएस | एन / ए |
'--------------------------------------------'

जहां महंगा __construct () है:

public function __construct() {
    $tmp = array(
        'foo' => 'bar',
        'this' => 'that'
    );  

    $in = in_array('those', $tmp);
}

ये परीक्षण इस सरल कोड पर आधारित हैं ।


56

nlaq इंगित करता है कि instanceofयदि परीक्षण एक ऐसे वर्ग का एक उदाहरण है जो एक इंटरफ़ेस को लागू करता है, तो इसका उपयोग किया जा सकता है।

लेकिन instanceofएक वर्ग प्रकार और एक इंटरफ़ेस के बीच अंतर नहीं करता है। आप नहीं जानते कि क्या वस्तु एक वर्ग है जिसे कहा जाता है IInterface

आप इसे और अधिक विशेष रूप से परीक्षण करने के लिए PHP में प्रतिबिंब एपीआई का उपयोग कर सकते हैं:

$class = new ReflectionClass('TheClass');
if ($class->implementsInterface('IInterface'))
{
  print "Yep!\n";
}

Http://php.net/manual/en/book.reflection.php देखें


2
इसका उपयोग "स्थिर" वर्गों पर किया जा सकता है
Znarkus

6
यह भी देखेंclass_implements()
जॉन कार्टर

@therefromhere: धन्यवाद, अच्छी टिप। यह एसपीएल विस्तार का हिस्सा है। मेरे जवाब में प्रतिबिंब विस्तार का उपयोग किया गया था।
बिल करविन

3
यदि आप नामस्थानों का उपयोग करते हैं तो एक ही नाम वाले इंटरफेस और कक्षाओं के बीच अस्पष्टता नहीं होगी और आप सुरक्षित रूप instanceofसे फिर से उपयोग कर सकते हैं ।
फ्लू

+1 के class_implements()बाद से इसके स्पष्ट रूप से क्लास_इम्प्लीमेंट और फिर in_array को कॉल करने के बजाय, एक पूर्ण प्रतिबिंब बनाने के बजाय
निकोलॉस

19

बस भविष्य की खोजों में मदद करने के लिए is_subclass_of एक अच्छा संस्करण है (PHP 5.3.7+ के लिए) -

if (is_subclass_of($my_class_instance, 'ISomeInterfaceName')){
    echo 'I can do it!';
}

5

आप निम्न कार्य भी कर सकते हैं

public function yourMethod(YourInterface $objectSupposedToBeImplementing) {
   //.....
}

यदि इंटरफ़ेस $objectSupposedToBeImplementingलागू नहीं होता है तो यह पुनर्प्राप्त करने योग्य त्रुटि को फेंक देगा YourInterface


3

अपडेट करें

is_a समारोह विकल्प के रूप में यहाँ याद आ रही है।

मैंने यह जांचने के लिए कुछ प्रदर्शन परीक्षण किए कि कौन से तरीके सबसे अधिक प्रदर्शन करने वाले हैं।

100k पुनरावृत्तियों पर परिणाम

      instanceof [object] took   7.67 ms | +  0% | ..........
            is_a [object] took  12.30 ms | + 60% | ................
             is_a [class] took  17.43 ms | +127% | ......................
class_implements [object] took  28.37 ms | +270% | ....................................
       reflection [class] took  34.17 ms | +346% | ............................................

कुछ डॉट्स को वास्तव में "महसूस" करने के लिए अंतर को देखें।

इसके द्वारा उत्पन्न: https://3v4l.org/8Cog7

निष्कर्ष

यदि आपके पास जाँच करने के लिए कोई वस्तु है, instance ofतो स्वीकृत उत्तर में बताए अनुसार उपयोग करें ।

यदि आपके पास जाँच करने, उपयोग करने के लिए एक वर्ग है is_a

बक्शीश

मामले को देखते हुए आप जिस वर्ग के इंटरफ़ेस पर आधारित होना चाहते हैं उसे आपके पास होना चाहिए, यह उपयोग करने के लिए अधिक अनुकूल है is_a। केवल एक अपवाद है - जब कंस्ट्रक्टर खाली है।

उदाहरण: is_a(<className>, <interfaceName>, true);

यह वापस आ जाएगी bool। तीसरा पैरामीटर " allow_string " यह क्लास को बिना इंस्टेंट किए क्लास के नामों की जांच करने की अनुमति देता है ।

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