इंटरफेस अन्य इंटरफेस का विस्तार (और इस तरह के विरासत तरीके से करने में) करना चाहिए


13

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

public interface IContextProvider
{
   IDataContext { get; set; }
   IAreaContext { get; set; }
}

इस इंटरफ़ेस का उपयोग अक्सर पूरे कार्यक्रम में किया जाता है और इसलिए मुझे उन वस्तुओं तक आसानी से पहुंच प्राप्त होती है जिनकी मुझे आवश्यकता होती है। हालांकि मेरे कार्यक्रम के एक हिस्से के काफी निचले स्तर पर मुझे किसी अन्य वर्ग तक पहुंच की आवश्यकता है जो IAreaContext का उपयोग करेगा और इसके कुछ संचालन करेगा। इसलिए मैंने इस निर्माण को करने के लिए एक और कारखाना इंटरफ़ेस बनाया है जिसे कहा जाता है:

public interface IEventContextFactory 
{
   IEventContext CreateEventContext(int eventId);
}

मेरे पास एक वर्ग है जो IContextProvider को लागू करता है और NinJect का उपयोग करके इंजेक्ट किया जाता है। मेरे पास समस्या यह है कि जिस क्षेत्र में मुझे इस IEventContextFactory का उपयोग करने की आवश्यकता है, वह केवल IContextProvider तक पहुंचता है और स्वयं एक अन्य वर्ग का उपयोग करता है जिसे इस नए इंटरफ़ेस की आवश्यकता होगी। मैं करने के लिए नहीं करना चाहते हैं का दृष्टांत के इस कार्यान्वयन IEventContextFactory और निम्न स्तर पर नहीं बल्कि होगा साथ काम IEventContextFactory भर इंटरफ़ेस। हालाँकि मैं यह भी नहीं चाहता कि निर्माणकर्ताओं के माध्यम से किसी अन्य पैरामीटर को इंजेक्ट किया जाए, क्योंकि यह उस कक्षा से होकर गुजरे जिसकी आवश्यकता है

// example of problem
public class MyClass
{
    public MyClass(IContextProvider context, IEventContextFactory event)
    {
       _context = context;
       _event = event;
    }

    public void DoSomething() 
    {
       // the only place _event is used in the class is to pass it through
       var myClass = new MyChildClass(_event);
       myClass.PerformCalculation();      
    }
}

तो मेरा मुख्य प्रश्न यह है कि क्या यह स्वीकार्य होगा या क्या ऐसा कुछ करना सामान्य या अच्छा अभ्यास है (इंटरफ़ेस किसी अन्य इंटरफ़ेस का विस्तार करें):

public interface IContextProvider : IEventContextFactory

या मुझे जो चाहिए उसे प्राप्त करने के लिए बेहतर विकल्पों पर विचार करना चाहिए। अगर मैंने सुझाव देने के लिए पर्याप्त जानकारी नहीं दी है तो मुझे बताएं और मैं और जानकारी प्रदान कर सकता हूं।


2
मैं आपके प्रश्न के शीर्षक को फिर से लिखूंगा क्योंकि "इंटरफ़ेस को इनहेरिट इंटरफेस चाहिए" क्योंकि कोई भी इंटरफ़ेस वास्तव में कुछ भी लागू नहीं करता है।
जेसी सी। स्लाइसर

2
सामान्य भाषा यह है कि एक इंटरफ़ेस अपने माता-पिता को "विस्तारित करता है", और (ऐसा करने में) मूल इंटरफ़ेस के तरीकों को "विरासत में" देता है, इसलिए मैं यहां "विस्तार" का उपयोग करने की सलाह दूंगा।
थियोडोर मर्डॉक

इंटरफेस माता-पिता का विस्तार कर सकते हैं, इसलिए यह बुरा अभ्यास क्यों होगा? यदि एक इंटरफ़ेस वैध रूप से किसी अन्य इंटरफ़ेस का सुपर-सेट है तो निश्चित रूप से इसे विस्तारित करना चाहिए।
रॉबिन विंसलो

जवाबों:


10

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

किसी भी समय यह इंटरफेस के लिए एक विरासत पदानुक्रम बनाने के लिए समझ में आता है, तो आपको चाहिए। यदि दो इंटरफेस हमेशा एक साथ मिलेंगे, तो उन्हें संभवतः विलय कर दिया जाना चाहिए।


6

हां, लेकिन केवल अगर यह समझ में आता है। अपने आप से निम्नलिखित प्रश्न पूछें और यदि एक या एक से अधिक लागू होते हैं तो दूसरे से एक इंटरफ़ेस प्राप्त करना स्वीकार्य है।

  1. क्या इंटरफ़ेस एक तार्किक रूप से इंटरफ़ेस B का विस्तार करता है, उदाहरण के लिए IList, ICollection की कार्यक्षमता को जोड़ता है।
  2. क्या इंटरफ़ेस एक अन्य इंटरफ़ेस द्वारा पहले से निर्दिष्ट व्यवहार को परिभाषित करने की आवश्यकता है, उदाहरण के लिए आईडीसिसोपयोगी को लागू करने के लिए यदि उसके पास संसाधन हैं जो कि इसे अधिक से अधिक प्रसारित किया जा सकता है तो IEnumerable को टिड्ड करने की आवश्यकता है।
  3. क्या इंटरफ़ेस A के प्रत्येक कार्यान्वयन में इंटरफ़ेस B द्वारा निर्दिष्ट व्यवहार की आवश्यकता होती है?

आपके उदाहरण में, मुझे नहीं लगता कि यह उन में से किसी के लिए हां का जवाब देता है। आप इसे अन्य संपत्ति के रूप में जोड़ना बेहतर हो सकते हैं:

public interface IContextProvider
{
   IDataContext DataContext { get; set; }
   IAreaContext AreaContext { get; set; }
   IEventContextFactory EventContextFactory { get; set; }
}

इंटरफ़ेस को विस्तारित करने की तुलना में यह कैसे एक संपत्ति बना देगा, या क्या यह बोलने के लिए बिल्ली को त्वचा देने का सिर्फ एक और तरीका है?
dreza

1
अंतर यह है कि यदि आप IContextProviderविस्तार करते हैं IEventContextFactory, तो ContextProviderकार्यान्वयन को उस पद्धति को भी लागू करना होगा। यदि आप इसे एक संपत्ति के रूप में जोड़ते हैं, तो आप कह रहे हैं कि एक ContextProviderहै, IEventContextFactoryलेकिन वास्तव में कार्यान्वयन विवरण नहीं जानता है।
ट्रेवर पिली

4

हां, एक इंटरफ़ेस को दूसरे से बढ़ाना ठीक है।

किसी विशेष मामले में सही काम करना है या नहीं यह सवाल इस बात पर निर्भर करता है कि क्या दोनों के बीच एक "रिश्ता" है।

वैध "रिश्ते" के लिए क्या आवश्यक है?

सबसे पहले, दो इंटरफेस के बीच एक वास्तविक अंतर होना चाहिए, अर्थात, ऐसे उदाहरण होने चाहिए जो कि पैरेंट इंटरफेस को लागू करते हैं, लेकिन चाइल्ड इंटरफेस को नहीं। यदि ऐसा नहीं है और कभी भी ऐसे उदाहरण नहीं होंगे जो दोनों इंटरफेस को लागू नहीं करते हैं, तो दो इंटरफेस को विलय करना चाहिए।

दूसरा, यह मामला होना चाहिए कि चाइल्ड इंटरफेस के प्रत्येक उदाहरण में माता-पिता का एक उदाहरण होना आवश्यक है: ऐसा कोई (उचित) तर्क नहीं है जिसके तहत आप चाइल्ड इंटरफेस का एक ऐसा उदाहरण बनाएंगे जो इंस्टेंस के उदाहरण के रूप में समझ में नहीं आएगा। अभिभावक इंटरफ़ेस।

यदि वे दोनों सच हैं, तो विरासत दोनों इंटरफेस के लिए सही संबंध है।


मुझे लगता है कि ऐसी कक्षाएं हैं जो केवल आधार इंटरफ़ेस का उपयोग करती हैं और व्युत्पन्न नहीं आवश्यक नहीं है। उदाहरण के लिए, इंटरफ़ेस IReadOnlyListउपयोगी हो सकता है, भले ही मेरी सभी सूची कक्षाएं कार्यान्वित हों IList(जो कि व्युत्पन्न है IReadOnlyList)।
svick

1

यदि एक इंटरफ़ेस हमेशा दूसरे की आवश्यकता / प्रदान करना चाहता है, तो आगे बढ़ें। मैंने इसे कुछ मामलों में देखा IDisposibleहै जिससे समझ में आया है। सामान्य तौर पर, आपको यह सुनिश्चित करना चाहिए कि कम से कम इंटरफेस में से एक जिम्मेदारी की तरह अधिक व्यवहार करता है।

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


उसके लिए धन्यवाद। एक जिम्मेदारी से अधिक एक विशेषता की तरह व्यवहार करने का क्या मतलब है?
dreza

@ ड्रेजा का मतलब है कि एसओएल में एसओएलडी में जिम्मेदारी, और स्कैला जैसे कुछ लक्षण हैं। अधिकतर यह अवधारणा कि इंटरफ़ेस आपकी समस्या को कैसे दर्शाता है। क्या यह समस्या के प्राथमिक भाग का प्रतिनिधित्व करता है या अन्यथा असमान प्रकारों के एक सामान्य टुकड़े में देखने का?
तेलस्टिन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.