c# - सी#कक्षा पुस्तकालयों को डिजाइन करते समय मुझे इंटरफ़ेस पर विरासत कब चुननी चाहिए?




oop design-patterns (5)

मेरे पास एक संख्या Processor कक्षाएं हैं जो दो बहुत ही अलग चीजें करेगी, लेकिन उन्हें सामान्य कोड ("नियंत्रण में उलटा" स्थिति कहा जाता है) से कहा जाता है।

मैं सोच रहा हूं कि डिजाइन विचारों के बारे में मुझे कब पता होना चाहिए कि क्या उन्हें BaseProcessor से सभी का उत्तराधिकारी होना चाहिए, या IProcessor को इंटरफ़ेस के रूप में कार्यान्वित करना चाहिए।


आम तौर पर, नियम इस तरह कुछ चला जाता है:

  • विरासत एक रिश्ते का वर्णन करता है
  • एक इंटरफ़ेस को कार्यान्वित करना एक कैन -डू रिश्ते का वर्णन करता है।

इसे कुछ और ठोस शब्दों में रखने के लिए, चलिए एक उदाहरण देखें। System.Drawing.Bitmap क्लास एक छवि है (और इस तरह, यह Image वर्ग से प्राप्त होती है), लेकिन यह डिस्पोजेक्ट भी कर सकती है , इसलिए यह IDisposable इंटरफ़ेस लागू करती है। यह serialization भी कर सकते हैं , तो यह ISerializable इंटरफेस से लागू करता है।

लेकिन अधिक व्यावहारिक रूप से, इंटरफेस अक्सर सी # में एकाधिक विरासत अनुकरण करने के लिए उपयोग किया जाता है। यदि आपके Processor क्लास को System.ComponentModel.Component जैसे किसी चीज़ से प्राप्त करने की आवश्यकता है, तो आपके पास IProcessor इंटरफ़ेस को लागू करने के अलावा बहुत कम विकल्प है।

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

इस तरह के सवालों के जवाब के लिए, मैं अक्सर .NET Framework Design दिशानिर्देशों पर जाता हूं, जिसमें कक्षाओं और इंटरफेस के बीच चयन करने के बारे में यह कहना है:

सामान्य रूप से, कक्षाएं abstractions को उजागर करने के लिए पसंदीदा निर्माण हैं।

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

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

[। ]

इंटरफेस के पक्ष में सबसे आम तर्कों में से एक यह है कि वे अनुबंध को कार्यान्वयन से अलग करने की अनुमति देते हैं। हालांकि, तर्क गलत तरीके से मानता है कि आप कक्षाओं का उपयोग करके कार्यान्वयन से अनुबंध अलग नहीं कर सकते हैं। उनके ठोस कार्यान्वयन से अलग असेंबली में रहने वाले सार वर्ग इस तरह के अलगाव को प्राप्त करने का एक शानदार तरीका हैं।

उनकी सामान्य सिफारिशें निम्नानुसार हैं:

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

क्रिस एंडरसन ने इस अंतिम सिद्धांत के साथ विशेष समझौते को व्यक्त किया, बहस करते हुए कहा कि:

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


इंटरफेस एक "अनुबंध" हैं, ये सुनिश्चित कर रहे हैं कि कुछ वर्ग सदस्यों के वांछित सेट - गुण, विधियों और घटनाओं को लागू करता है।

बेस वर्ग (ठोस या सार, कोई फर्क नहीं पड़ता) कुछ इकाई के archetype हैं। ये ये संस्थाएं हैं जो कुछ वास्तविक भौतिक या वैचारिक में आम है।

इंटरफेस का उपयोग कब करें?

जब भी किसी प्रकार को यह घोषित करने की आवश्यकता होती है, कम से कम, कुछ व्यवहार और गुण होते हैं जिन्हें उपभोक्ता को कुछ कार्य पूरा करने के लिए उनकी देखभाल करनी चाहिए और उनका उपयोग करना चाहिए।

बेस क्लास (कंक्रीट और / या अमूर्त) का उपयोग कब करें

जब भी संस्थाओं का एक समूह समान आर्केटाइप साझा करता है, जिसका अर्थ है बी बी को विरासत में मिलता है क्योंकि बी अंतर के साथ ए है, लेकिन बी को ए के रूप में पहचाना जा सकता है।

उदाहरण:

चलो टेबल के बारे में बात करते हैं।

  • हम रीसाइक्टेबल टेबल स्वीकार करते हैं => इसे "आईआरसाइक्टेबलटेबल" जैसे इंटरफेस के साथ परिभाषित किया जाना चाहिए ताकि सभी रीसाइक्टेबल टेबलों में "रीसायकल" विधि हो

  • हम डेस्कटॉप टेबल चाहते हैं => यह विरासत के साथ परिभाषित किया जाना चाहिए। एक "डेस्कटॉप टेबल" एक "टेबल" है। सभी तालिकाओं में सामान्य गुण होते हैं और व्यवहार होते हैं और डेस्कटॉप वाले में ऐसी चीजें शामिल होती हैं जो डेस्कटॉप टेबल को अन्य प्रकार की तालिकाओं से अलग बनाती हैं।

मैं एसोसिएशन के बारे में बात कर सकता हूं, ऑब्जेक्ट ग्राफ में दोनों मामलों का अर्थ, लेकिन मेरी विनम्र राय में, अगर मुझे एक वैचारिक दृष्टिकोण में तर्क देने की ज़रूरत है, तो मैं वास्तव में इस तर्क के साथ जवाब दूंगा।


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


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

या यदि विरासत से बचा नहीं जा सकता है, तो शायद दोनों को एक साथ उपयोग करने का एक अच्छा विचार है। एक इंटरफेस लागू करता है जो एक सार आधार वर्ग बनाएँ। आपके मामले में, प्रोसेसरबेस एक आईपी प्रोसेसर लागू करता है।

एएसपी.नेट एमवीसी में कंट्रोलरबेस और आईकंट्रोलर के समान।


रिचर्ड,

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

इस तरह, यदि आपको भविष्य में एक आईप्रोसेसर की आवश्यकता है जो बेसप्रोसेसर की सेवाओं के लिए नहीं है, तो उसे यह नहीं है (और संभवतः इसे छुपाएं) ... लेकिन जो लोग चाहते हैं वे इसे प्राप्त कर सकते हैं ... काटना डुप्लिकेट कोड / अवधारणाओं में।

बस मेरी विनम्र राय।

चीयर्स। कीथ।





interface