किसी भी कार्यान्वयन के लिए इंटरफ़ेस संदर्भ को कास्टिंग करने से लेखक का क्या मतलब है?


17

मैं वर्तमान में C # को मास्टर करने की कोशिश में हूं, इसलिए मैं गैरी मैकलीन हॉल द्वारा C # के माध्यम से Adaptive Code पढ़ रहा हूं ।

वह पैटर्न और विरोधी पैटर्न के बारे में लिखते हैं। कार्यान्वयन बनाम इंटरफेस भाग में वह निम्नलिखित लिखते हैं:

डेवलपर्स जो इंटरफेस के लिए प्रोग्रामिंग की अवधारणा के लिए नए हैं, अक्सर इंटरफ़ेस के पीछे क्या है, यह बताने में कठिनाई होती है।

संकलन के समय, इंटरफ़ेस के किसी भी ग्राहक को यह पता नहीं होना चाहिए कि वह किस इंटरफ़ेस का उपयोग कर रहा है। ऐसा ज्ञान गलत धारणाओं को जन्म दे सकता है जो क्लाइंट को इंटरफ़ेस के एक विशिष्ट कार्यान्वयन के लिए जोड़े।

उस सामान्य उदाहरण की कल्पना करें जिसमें एक वर्ग को लगातार भंडारण में रिकॉर्ड बचाने की आवश्यकता होती है। ऐसा करने के लिए, यह सही ढंग से एक इंटरफ़ेस को दर्शाता है, जो उपयोग किए गए निरंतर भंडारण तंत्र के विवरण को छुपाता है। हालांकि, इस बारे में कोई भी धारणा बनाना सही नहीं होगा कि इंटरफ़ेस का कार्यान्वयन रन टाइम में किसके लिए किया जा रहा है। उदाहरण के लिए, किसी भी कार्यान्वयन के लिए इंटरफ़ेस संदर्भ को कास्टिंग करना हमेशा एक बुरा विचार है।

यह भाषा की बाधा हो सकती है, या मेरे अनुभव की कमी हो सकती है, लेकिन मुझे इसका मतलब समझ में नहीं आता है। यहाँ मैं समझता हूँ:

मेरे पास C # का अभ्यास करने के लिए एक निशुल्क मज़ा परियोजना है। वहाँ मेरा एक वर्ग है:

public class SomeClass...

इस वर्ग का उपयोग बहुत सारी जगहों पर किया जाता है। C # सीखने के दौरान, मैंने पढ़ा कि एक इंटरफ़ेस के साथ अमूर्त करना बेहतर है, इसलिए मैंने निम्नलिखित कार्य किया

public interface ISomeClass <- Here I made a "contract" of all the public methods and properties SomeClass needs to have.

public class SomeClass : ISomeClass <- Same as before. All implementation here.

इसलिए मैं कुछ क्लास के सभी संदर्भों में चला गया और उनकी जगह ISomeClass ने ले ली।

निर्माण में छोड़कर, जहाँ मैंने लिखा था:

ISomeClass myClass = new SomeClass();

क्या मैं सही ढंग से समझ रहा हूं कि यह गलत है? यदि हाँ, तो क्यों, और मुझे इसके बजाय क्या करना चाहिए?


25
आपके उदाहरण में कहीं भी आप इंटरफ़ेस प्रकार की वस्तु को कार्यान्वयन प्रकार में नहीं डाल रहे हैं। आप एक इंटरफ़ेस चर में कार्यान्वयन प्रकार के कुछ असाइन कर रहे हैं, जो पूरी तरह से ठीक और सही है।
केलथ

1
आपके द्वारा लिखे गए "कंस्ट्रक्टर में" का क्या मतलब है ISomeClass myClass = new SomeClass();? यदि आप वास्तव में इसका मतलब है कि, कंस्ट्रक्टर में पुनरावृत्ति है, तो शायद आप जो चाहते हैं वह नहीं है। उम्मीद है कि आपका मतलब "निर्माण" अर्थात आवंटन में है, शायद, लेकिन खुद कंस्ट्रक्टर में नहीं। ?
एरिक इद्दत

@ एरिक: हाँ। काम चल रहा है। तुम सही हो। सही सवाल करेंगे। धन्यवाद
मार्शल

मजेदार तथ्य: एफ # की उस संबंध में सी # से बेहतर कहानी है - यह निहित इंटरफ़ेस कार्यान्वयन के साथ दूर करता है, इसलिए जब भी आप एक इंटरफ़ेस विधि को कॉल करना चाहते हैं, तो आपको इंटरफ़ेस प्रकार को बनाए रखने की आवश्यकता है। इससे यह स्पष्ट हो जाता है कि आप कब और कैसे अपने कोड में इंटरफेस का उपयोग कर रहे हैं, और प्रोग्रामिंग को भाषा में बहुत अधिक अंतर्क्रिया करने के लिए बनाता है।
स्क्रव टीपी

3
यह थोड़ा ऑफ-टॉपिक है, लेकिन मुझे लगता है कि लेखक ने लोगों को इस समस्या के बारे में गलत जानकारी दी है। मेरी राय में, समस्या यह है कि अवधारणा के लिए नए लोग अच्छे इंटरफेस बनाना नहीं जानते हैं। बहुत विशिष्ट इंटरफेस बनाना बहुत आसान है जो वास्तव में कोई भी सामान्यता प्रदान नहीं करता है (जो कि अच्छी तरह से हो सकता है ISomeClass), लेकिन बहुत सामान्य इंटरफेस बनाना भी आसान है, जिसके लिए उपयोगी कोड लिखना असंभव है, जिसके लिए एकमात्र विकल्प है इंटरफ़ेस को फिर से जोड़ना और कोड को फिर से लिखना या डाउनकास्ट करना है।
डेरेक एल्किन्स ने

जवाबों:


37

अपनी कक्षा को एक इंटरफ़ेस में बदलना कुछ ऐसा है जिस पर आपको विचार करना चाहिए और केवल तभी जब आप उक्त इंटरफ़ेस के अन्य कार्यान्वयन को लिखने का इरादा रखते हैं या भविष्य में ऐसा करने की प्रबल संभावना है।

तो शायद SomeClassऔर ISomeClassयह एक बुरा उदाहरण है, क्योंकि यह एक OracleObjectSerializerवर्ग और एक IOracleObjectSerializerइंटरफेस होने जैसा होगा ।

एक अधिक सटीक उदाहरण कुछ ऐसा होगा OracleObjectSerializerऔर ए IObjectSerializer। आपके कार्यक्रम में एकमात्र स्थान जहां आप परवाह करते हैं कि उदाहरण के निर्माण के समय कौन सा कार्यान्वयन उपयोग करना है। फ़ैक्टरी पैटर्न का उपयोग करके कभी-कभी इसे और भी कम कर दिया जाता है।

आपके कार्यक्रम में हर जगह IObjectSerializerको परवाह नहीं है कि यह कैसे काम करता है। अब एक सेकंड के लिए मान लीजिए कि आपके पास SQLServerObjectSerializerइसके अलावा कार्यान्वयन भी है OracleObjectSerializer। अब मान लें कि आपको सेट करने के लिए कुछ विशेष गुण सेट करने की आवश्यकता है और वह विधि केवल OracleObjectSerializer में मौजूद है, SQLServerObjectSerializer नहीं।

इसके बारे में जाने के दो तरीके हैं: गलत तरीका और लिस्कोव प्रतिस्थापन सिद्धांत

गलत तरीका है

गलत तरीका, और आपकी पुस्तक में उल्लिखित बहुत ही उदाहरण है, उदाहरण के लिए IObjectSerializerऔर इसे कास्ट करने के लिए OracleObjectSerializerऔर फिर उस तरीके setPropertyपर कॉल करें OracleObjectSerializer। यह बुरा है क्योंकि भले ही आप एक उदाहरण होने के लिए जानते OracleObjectSerializerहों, आप अपने कार्यक्रम में एक और बिंदु पेश कर रहे हैं, जहां आपको यह जानने की परवाह है कि कार्यान्वयन क्या है। जब यह कार्यान्वयन बदल जाता है, और संभवतः यह जल्द या बाद में होगा यदि आपके पास कई कार्यान्वयन हैं, तो सबसे अच्छा मामला है, आपको इन सभी स्थानों को खोजने और सही समायोजन करने की आवश्यकता होगी। सबसे खराब स्थिति, आप एक IObjectSerializerउदाहरण देते हैं OracleObjectSerializerऔर आपको उत्पादन में एक विफलता मिलती है।

लिसकोव प्रतिस्थापन सिद्धांत

लिस्कोव ने कहा कि आपको setPropertyक्रियान्वयन वर्ग में तरीकों की कभी भी आवश्यकता नहीं होनी चाहिए क्योंकि मेरे मामले में OracleObjectSerializerअगर ठीक से किया जाए। यदि आप किसी वर्ग के OracleObjectSerializerलिए सार करते हैं IObjectSerializer, तो आपको उस कक्षा का उपयोग करने के लिए आवश्यक सभी तरीकों को शामिल करना चाहिए, और यदि आप नहीं कर सकते हैं, तो आपके अमूर्त के साथ कुछ गलत है ( उदाहरण के लिए कार्यान्वयन के Dogरूप में वर्ग के काम करने की कोशिश करना IPerson)।

सही तरीका एक setPropertyतरीका प्रदान करना होगा IObjectSerializerSQLServerObjectSerializerइस setPropertyपद्धति के समान तरीके आदर्श रूप से काम करेंगे । बेहतर अभी भी, आप संपत्ति के नाम को मानकीकृत करते हैं, Enumजहां प्रत्येक कार्यान्वयन उस डेटाबेस में अपनी खुद की डेटाबेस शब्दावली के लिए अनुवाद करता है।

सीधे शब्दों में कहें, एक ISomeClassका उपयोग कर यह केवल आधा है। आपको इसे उस विधि से बाहर निकालने की आवश्यकता नहीं है जो इसके निर्माण के लिए जिम्मेदार है। ऐसा करने के लिए लगभग निश्चित रूप से एक गंभीर डिजाइन गलती है।


1
मुझे ऐसा लगता है कि, अगर आप डाली जा रहे हैं IObjectSerializerकरने के लिए OracleObjectSerializerहै क्योंकि आप "पता" है कि इस यह क्या है है, तो आप और अधिक महत्वपूर्ण खुद के साथ ईमानदार (, जो दूसरों के लिए इस कोड को बनाए रखने सकता है के साथ किया जाना चाहिए, जो अपने भविष्य के शामिल हो सकते हैं स्वयं), और OracleObjectSerializerजहां से यह बनाया जाता है, जहां इसका उपयोग किया जाता है, वहां से सभी तरह का उपयोग करें। यह बहुत ही सार्वजनिक और स्पष्ट करता है कि आप एक विशेष कार्यान्वयन पर निर्भरता का परिचय दे रहे हैं - और काम और कुरूपता जो कि, स्वयं, एक मजबूत संकेत है कि कुछ गलत है, में शामिल है।
केरेन

(और, यदि किसी कारण तुम सच के लिए है एक विशेष कार्यान्वयन पर निर्भर रहना पड़ता है, यह एक बहुत स्पष्ट हो जाता है कि यह आप क्या कर रहे हैं और है कि आप इसे इरादे और उद्देश्य के साथ कर रहे हैं। यह कभी नहीं निश्चित रूप से होता है "चाहिए", और 99% बार ऐसा लग सकता है कि यह वास्तव में ऐसा नहीं हो रहा है और आपको चीजों को ठीक करना चाहिए, लेकिन कुछ भी कभी भी 100% निश्चित नहीं है या जिस तरह से चीजें होनी चाहिए।)
KRyan

@KRyan बिल्कुल। अगर आपको इसकी आवश्यकता है तो एब्सट्रैक्शन का उपयोग केवल तभी किया जाना चाहिए। अमूर्तता का उपयोग करना जब यह आवश्यक नहीं है तो केवल कोड को समझने के लिए थोड़ा और अधिक कठिन बनाने का कार्य करता है।
नील

29

स्वीकृत उत्तर सही और बहुत उपयोगी है, लेकिन मैं विशेष रूप से आपके द्वारा पूछे गए कोड की पंक्ति को संक्षेप में संबोधित करना चाहूंगा:

ISomeClass myClass = new SomeClass();

मोटे तौर पर, यह भयानक नहीं है। जब भी संभव हो ऐसा करने से बचना चाहिए:

void someMethod(ISomeClass interface){
    SomeClass cast = (SomeClass)interface;
}

जहां आपका कोड बाहरी रूप से एक इंटरफ़ेस प्रदान किया जाता है, लेकिन आंतरिक रूप से इसे एक विशिष्ट कार्यान्वयन के लिए डाल देता है, "क्योंकि मुझे पता है कि यह केवल" कार्यान्वयन "होगा। यहां तक ​​कि अगर यह अंत तक सही था, तो इंटरफ़ेस का उपयोग करके और इसे क्रियान्वयन के लिए कास्टिंग करके आप स्वेच्छा से वास्तविक प्रकार की सुरक्षा छोड़ रहे हैं, ताकि आप अमूर्त का उपयोग करने का दिखावा कर सकें। यदि बाद में किसी और को कोड पर काम करना था और एक ऐसा तरीका देखना था जो एक इंटरफ़ेस पैरामीटर को स्वीकार करता है, तो वे मान लेंगे कि उस इंटरफ़ेस का कोई भी कार्यान्वयन पास करने के लिए एक वैध विकल्प है। यह स्वयं भी थोड़ा नीचे हो सकता है। आपके द्वारा यह भूल जाने के बाद कि कोई विशिष्ट विधि किन मानकों की आवश्यकता है, के बारे में बताती है। यदि आपको कभी किसी इंटरफ़ेस से किसी विशिष्ट कार्यान्वयन के लिए कास्ट करने की आवश्यकता महसूस होती है, तो या तो इंटरफ़ेस, कार्यान्वयन, या कोड जो उन्हें संदर्भित करता है गलत तरीके से डिज़ाइन किया गया है और बदलना चाहिए। उदाहरण के लिए, यदि विधि केवल तभी काम करती है जब तर्क पास किया गया एक विशिष्ट वर्ग है, तो पैरामीटर को केवल उस वर्ग को स्वीकार करना चाहिए।

अब, अपने कंस्ट्रक्टर कॉल को वापस देख रहा है

ISomeClass myClass = new SomeClass();

कास्टिंग से समस्याएं वास्तव में लागू नहीं होती हैं। इसमें से कोई भी बाहरी रूप से उजागर नहीं होता है, इसलिए इसके साथ कोई विशेष जोखिम नहीं जुड़ा है। अनिवार्य रूप से, कोड की यह लाइन स्वयं एक कार्यान्वयन विवरण है जिसे इंटरफेस को शुरू करने के लिए सार के लिए डिज़ाइन किया गया है, इसलिए एक बाहरी पर्यवेक्षक इसे उसी तरह से काम करते हुए देखेगा कि वे क्या करते हैं। हालाँकि, यह भी एक अंतरफलक के अस्तित्व से कुछ भी नहीं है। आपके myClassपास प्रकार है ISomeClass, लेकिन इसका कोई कारण नहीं है क्योंकि इसे हमेशा एक विशिष्ट कार्यान्वयन सौंपा जाता है,SomeClass। कुछ मामूली संभावित लाभ हैं, जैसे कि कोडर में कार्यान्वयन को स्वैप करने में सक्षम होना बस कंस्ट्रक्टर कॉल को बदलकर, या उस वेरिएबल को बाद में एक अलग कार्यान्वयन के लिए पुन: असाइन करना, लेकिन जब तक कि कहीं और न हो जिसके लिए चर को इंटरफ़ेस के बजाय टाइप किया जाना चाहिए इस पैटर्न को लागू करने से आपका कोड ऐसा दिखता है जैसे इंटरफेस का उपयोग केवल रटे द्वारा किया गया था, न कि इंटरफेस के लाभों की वास्तविक समझ से बाहर।


1
अपाचे मैथ Cartesian3D सोर्स, लाइन 286 के साथ ऐसा करता है , जो वास्तव में कष्टप्रद हो सकता है।
J_F_B_M 15

1
यह वास्तव में सही उत्तर है जो मूल प्रश्न को संबोधित करता है।
बेंजामिन ग्रुएनबाउम

2

मुझे लगता है कि एक खराब उदाहरण के साथ अपना कोड दिखाना आसान है:

public interface ISomeClass
{
    void DoThing();
}

public class SomeClass : ISomeClass
{
    public void DoThing()
    {
       // Mine for BitCoin
    }

}

public class AnotherClass : ISomeClass
{
    public void DoThing()
    {
        // Mine for oil
    }
    public Decimal Depth;
 }

 void main()
 {
     ISomeClass task = new SomeClass();

     task.DoThing(); //  This is good

     Console.WriteLine("Depth = {0}", ((AnotherClass)task).Depth); <-- The task object will not have this field
 }

समस्या यह है कि जब आप शुरू में कोड लिखते हैं, तो शायद उस इंटरफ़ेस का केवल एक कार्यान्वयन होता है, ताकि कास्टिंग अभी भी काम करेगी, यह सिर्फ इतना है कि भविष्य में, आप एक और वर्ग लागू कर सकते हैं और फिर (जैसा कि मेरा उदाहरण दिखाता है), आप कोशिश करें और डेटा का उपयोग करें जो आपके द्वारा उपयोग की जा रही वस्तु में मौजूद नहीं है।


क्यों नमस्कार, सर। कोई भी कभी भी आपको बताता है कि आप कितने सुंदर हैं?
नील

2

स्पष्टता के लिए, आइए कास्टिंग को परिभाषित करें।

कास्टिंग को जबरन एक प्रकार से दूसरे प्रकार में परिवर्तित करना है। एक सामान्य उदाहरण एक पूर्णांक संख्या के लिए एक पूर्णांक प्रकार कास्टिंग है। कास्टिंग करते समय एक विशिष्ट रूपांतरण निर्दिष्ट किया जा सकता है लेकिन डिफ़ॉल्ट बस बिट्स को फिर से व्याख्या करना है।

इस Microsoft डॉक्स पृष्ठ से कास्टिंग का एक उदाहरण यहां दिया गया है ।

// Create a new derived type.  
Giraffe g = new Giraffe();  

// Implicit conversion to base type is safe.  
Animal a = g;  

// Explicit conversion is required to cast back  
// to derived type. Note: This will compile but will  
// throw an exception at run time if the right-side  
// object is not in fact a Giraffe.  
Giraffe g2 = (Giraffe) a;  

आप एक ही काम कर सकते हैं और कुछ ऐसा डाल सकते हैं जो एक इंटरफ़ेस को उस इंटरफ़ेस के किसी विशेष कार्यान्वयन के लिए लागू करता है, लेकिन आपको ऐसा नहीं करना चाहिए क्योंकि यदि आप अपेक्षा से भिन्न कार्यान्वयन का उपयोग करते हैं तो त्रुटि या अप्रत्याशित व्यवहार होगा।


1
"कास्टिंग एक प्रकार से दूसरे प्रकार में परिवर्तित हो रही है।" - नंबर कास्टिंग स्पष्ट रूप से एक प्रकार से दूसरे प्रकार में परिवर्तित कर रही है। (विशेष रूप से, "कास्ट" उस रूपांतरण को निर्दिष्ट करने के लिए उपयोग किए गए वाक्यविन्यास का नाम है।) निहित रूपांतरण नहीं हैं। "कास्टिंग करते समय एक विशिष्ट रूपांतरण निर्दिष्ट किया जा सकता है लेकिन डिफ़ॉल्ट बस बिट्स को फिर से व्याख्या करना है।" -- हरगिज नहीं। बहुत सारे रूपांतरण हैं, दोनों निहित और स्पष्ट हैं, जिसमें बिट पैटर्न में महत्वपूर्ण परिवर्तन शामिल हैं।
hvd

@hvd मैंने कास्टिंग के गवाह के बारे में अब सुधार किया है। जब मैंने कहा कि डिफ़ॉल्ट केवल बिट्स को फिर से व्याख्या करना है, तो मैं यह व्यक्त करने की कोशिश कर रहा था कि यदि आप अपना खुद का प्रकार बनाने के लिए थे, तो उन मामलों में जहां एक डाली स्वचालित रूप से परिभाषित होती है, जब आप इसे दूसरे प्रकार में डालते हैं तो बिट्स की फिर से व्याख्या की जाएगी। । ऊपर दिए गए Animal/ Giraffeउदाहरण में, यदि आप कर रहे थे तो Animal a = (Animal)g;बिट्स की पुन: व्याख्या की जाएगी, (किसी भी जिराफ़ विशिष्ट डेटा को "इस ऑब्जेक्ट का हिस्सा नहीं" के रूप में व्याख्या किया जाएगा)।
18:17 बजे रयान 1729

एचवीडी क्या कहता है, इसके बावजूद, लोग अक्सर निहितार्थ के संदर्भ में "कास्ट" शब्द का उपयोग करते हैं; उदाहरण के लिए https://www.google.com/search?q="implicit+cast"&tbm=bks देखें । तकनीकी रूप से मुझे लगता है कि स्पष्ट रूप से रूपांतरण के लिए "कास्ट" शब्द को आरक्षित करना अधिक सही है, जब तक कि आप भ्रमित न हों जब अन्य इसे अलग-अलग उपयोग करते हैं।
21

0

मेरे 5 सेंट:

वे सभी उदाहरण ठीक हैं, लेकिन वे वास्तविक दुनिया के उदाहरण नहीं हैं और उन्होंने वास्तविक दुनिया के इरादों को नहीं दिखाया है।

मुझे C # नहीं पता है इसलिए मैं सार उदाहरण (जावा और C ++ के बीच मिश्रण) दूंगा। आशा है कि यह ठीक है।

मान लीजिए कि आपके पास इंटरफ़ेस है iList:

interface iList<Key,Value>{
   bool add(Key k, Value v);
   bool remove(Element e);
   Value get(Key k);
}

अब मान लें कि बहुत सारे कार्यान्वयन हैं:

  • डायनामिकअरेलिस्ट - अंत में डालने और हटाने के लिए तेजी से फ्लैट सरणी का उपयोग करता है।
  • लिंक्डलिस्ट - डबल लिंक्ड सूची का उपयोग करता है, सामने और अंत में डालने के लिए तेजी से।
  • एवीएलट्रीलिस्ट - एवीएल ट्री का उपयोग करता है, सब कुछ करने के लिए तेजी से, लेकिन बहुत सारी मेमोरी का उपयोग करता है
  • SkipList - SkipList का उपयोग करता है, सब कुछ करने के लिए तेज़, AVL ट्री की तुलना में धीमा, लेकिन कम मेमोरी का उपयोग करता है।
  • HashList - HashTable का उपयोग करता है

बहुत सारे अलग-अलग कार्यान्वयन के बारे में सोच सकते हैं।

अब मान लें कि हमारे पास निम्नलिखित कोड हैं:

uint begin_size = 1000;
iList list = new DynamicArrayList(begin_size);

यह स्पष्ट रूप से हमारे इरादे को दर्शाता है जिसका हम उपयोग करना चाहते हैं iList। निश्चित रूप से हम अब DynamicArrayListविशिष्ट संचालन करने में सक्षम नहीं हैं , लेकिन हमें इसकी आवश्यकता है iList

निम्नलिखित कोड पर विचार करें:

iList list = factory.getList();

अब हमें यह भी पता नहीं है कि कार्यान्वयन क्या है। यह अंतिम उदाहरण अक्सर छवि प्रसंस्करण में उपयोग किया जाता है जब आप डिस्क से कुछ फ़ाइल लोड करते हैं और आपको इसकी फ़ाइल प्रकार (gif, jpeg, png, bmp ...) की आवश्यकता नहीं होती है, लेकिन आप जो चाहते हैं वह कुछ छवि हेरफेर करना है (फ्लिप, स्केल, अंत में png के रूप में सहेजें)।


0

आपके पास एक इंटरफ़ेस ISomeClass है, और एक ऑब्जेक्ट myObject है जिसके बारे में आपको अपने कोड से कुछ भी नहीं पता है सिवाय इसके कि इसे ISomeClass को लागू करने के लिए घोषित किया गया है।

आपके पास एक क्लास SomeClass है, जिसे आप इंटरफ़ेस ISomeClass लागू करते हैं। आप जानते हैं कि क्योंकि यह ISomeClass को लागू करने के लिए घोषित किया गया है, या आपने इसे ISomeClass को लागू करने के लिए स्वयं लागू किया है।

MyClass को SomeClass में डालने में क्या गलत है? दो बातें गलत हैं। एक, आप वास्तव में नहीं जानते हैं कि myClass कुछ ऐसा है जिसे SomeClass (SomeClass का उदाहरण या SomeClass का उपवर्ग) में परिवर्तित किया जा सकता है, इसलिए कलाकार गलत हो सकते हैं। दो, आपको ऐसा नहीं करना चाहिए। आप एक iSomeClass के रूप में घोषित myClass के साथ काम कर रहे हों, और ISomeClass विधियों का उपयोग करें।

वह बिंदु जहां आपको एक SomeClass ऑब्जेक्ट मिलता है, जब एक इंटरफ़ेस विधि कहा जाता है। कुछ बिंदु पर आप myClass.myMethod () कहते हैं, जो इंटरफ़ेस में घोषित किया गया है, लेकिन SomeClass में इसका कार्यान्वयन है, और निश्चित रूप से संभवतः कई अन्य वर्गों में जो कि ISomeClass को लागू करता है। यदि आपके SomeClass.myMethod कोड में कॉल समाप्त हो जाती है, तो आप जानते हैं कि Self SomeClass का एक उदाहरण है, और उस समय यह बिल्कुल ठीक है और वास्तव में इसे SomeClass ऑब्जेक्ट के रूप में उपयोग करने के लिए सही है। बेशक अगर यह वास्तव में OtherClass का उदाहरण है और SomeClass का नहीं है, तो आप SomeClass कोड पर नहीं पहुंचेंगे।

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