क्या यह एक इंटरफ़ेस को परिभाषित करने के लिए समझ में आता है अगर मेरे पास पहले से ही एक सार वर्ग है?


12

मेरे पास कुछ डिफ़ॉल्ट / साझा कार्यक्षमता के साथ एक वर्ग है। मैं abstract classइसके लिए उपयोग करता हूं :

public interface ITypeNameMapper
{
    string Map(TypeDefinition typeDefinition);
}

public abstract class TypeNameMapper : ITypeNameMapper
{
    public virtual string Map(TypeDefinition typeDefinition)
    {
        if (typeDefinition is ClassDefinition classDefinition)
        {
            return Map(classDefinition);
        }
        ...

        throw new ArgumentOutOfRangeException(nameof(typeDefinition));
    }

    protected abstract string Map(ClassDefinition classDefinition);
}

जैसा कि आप देख सकते हैं, मेरे पास इंटरफ़ेस भी है ITypeNameMapper। क्या यह इस इंटरफ़ेस को परिभाषित करने के लिए समझ में आता है अगर मेरे पास पहले से ही एक सार वर्ग है TypeNameMapperया abstract classबस पर्याप्त है?

TypeDefinition इस न्यूनतम उदाहरण में भी सार है।


4
सिर्फ FYI करें - OOD में, कोड में प्रकारों की जाँच करना इस बात का संकेत है कि आपकी कक्षा की पदानुक्रम सही नहीं है - यह आपको बता रही है कि आप जिस प्रकार की जाँच कर रहे हैं उससे व्युत्पन्न वर्ग बनाएँ। तो, इस मामले में, आप एक इंटरफ़ेस चाहते हैं ITypeMapper जो एक मानचित्र () विधि को निर्दिष्ट करता है और फिर उस इंटरफ़ेस को TypeDefinition और ClassDefinition वर्गों दोनों में लागू करता है। इस तरह, आपका ClassAssembler बस ITypeMappers की सूची के माध्यम से पुनरावृत्ति करता है, प्रत्येक पर मानचित्र () को बुलाता है, और दोनों प्रकार से वांछित स्ट्रिंग प्राप्त करता है क्योंकि उनका प्रत्येक का अपना कार्यान्वयन है।
रोडनी पी। बारबाती

1
एक इंटरफ़ेस के स्थान पर एक बेस क्लास का उपयोग करना, जब तक कि आपको पूरी तरह से करना न हो, "बर्निंग द बेस" कहा जाता है। यदि यह एक इंटरफेस के साथ किया जा सकता है, तो इसे एक इंटरफेस के साथ करें। अमूर्त वर्ग तब एक सहायक अतिरिक्त बन जाता है। artima.com/intv/dotnet.html विशेष रूप से, रीमोटिंग के लिए आपको MarsBBRROObject से प्राप्त करने की आवश्यकता होती है, ताकि यदि आप चाहते हैं कि आपको हटा दिया जाए तो आप किसी और चीज़ से प्राप्त नहीं कर सकते
बेन

@ RodneyP.Barbati काम नहीं करेगा अगर मैं एक ही प्रकार के कई मैपर रखना चाहता हूं जिसे मैं स्थिति के आधार पर स्विच कर सकता हूं
कोनराड

1
@ आधार को जलाना दिलचस्प है। मणि के लिए धन्यवाद!
कोनराड

@Konrad यह गलत है - इंटरफ़ेस के किसी अन्य कार्यान्वयन को कॉल करके आपको इंटरफ़ेस को लागू करने से रोकना कुछ भी नहीं है, इसलिए, प्रत्येक प्रकार में एक प्लग करने योग्य कार्यान्वयन हो सकता है जिसे आप प्रकार में कार्यान्वयन के माध्यम से उजागर करते हैं।
रोडनी पी। बारबती

जवाबों:


31

हां, क्योंकि C # इंटरफेस के अलावा कई उत्तराधिकार की अनुमति नहीं देता है।

इसलिए अगर मेरे पास एक वर्ग है जो टाइपनामेपर और समथेल्सेप मैपर दोनों है जो मैं कर सकता हूं:

class MultiFunctionalClass : ITypeNameMapper, ISomethingelseMapper 
{
    private TypeNameMapper map1
    private SomethingelseMapper map2

    public string Map(TypeDefinition typeDefinition) { return map1.Map(typeDefintion);}

    public string Map(OtherDef otherDef) { return map2.Map(orderDef); }
}

4
@ लिट: एकल जिम्मेदारी वास्तव में एक योगदान कारक है क्योंकि विरासत की आवश्यकता क्यों है। तीन संभावित लक्षण पर विचार करें: ICanFly, ICanRun, ICanSwim। आपको 8 जीव वर्गों को बनाने की जरूरत है, लक्षणों के हर संयोजन के लिए एक (YYY, YYN, YNY, ..., NNY, NNN)। एसआरपी बताता है कि आप प्रत्येक व्यवहार (मक्खी, दौड़, तैरना) को एक बार लागू करते हैं और फिर उन्हें 8 प्राणियों पर फिर से लागू करते हैं। यहां रचना और भी बेहतर होगी, लेकिन एक सेकंड के लिए रचना की अनदेखी करना, आपको पहले से ही एसआरपी के कारण कई अलग-अलग पुन: प्रयोज्य व्यवहारों को विरासत में प्राप्त करने / लागू करने की आवश्यकता को देखना चाहिए ।
फ्लोटर

4
@Konrad कि मैं क्या मतलब है। यदि आप इंटरफ़ेस लिखते हैं, और कभी भी इसकी आवश्यकता नहीं होती है, तो लागत 3 एलओसी है। आप इंटरफ़ेस बारे में नहीं है और आप इसे क्या ज़रूरत है मिल जाए, लागत हो सकता है अपने पूरे आवेदन पुनर्रचना हो।
इवान

3
(१) इंटरफेस लागू करना विरासत है? (२) प्रश्न और उत्तर दोनों योग्य होने चाहिए। "निर्भर करता है।" (3) एकाधिक वंशानुक्रम के लिए उस पर चेतावनी स्टिकर की आवश्यकता होती है। (४) मैं आपको K के लालित्यपूर्ण औपचारिक interfaceकदाचार को दिखा सकता था .. निरर्थक कार्यान्वयन जो आधार में होना चाहिए - जो कि स्वतंत्र रूप से विकसित हो रहे हैं !, सशर्त तर्क परिवर्तन के तरीकों, टूटे हुए इनकैप्सुलेशन, नॉन-प्रिलेंट एबट्रैक्शन की चाह में इस कबाड़ को चलाते हैं। मेरा पसंदीदा: 1-विधि कक्षाएं प्रत्येक अपने स्वयं के 1-पद्धति को लागू करती हैं interface, प्रत्येक w / केवल एक उदाहरण। ... आदि, आदि और आदि
रडार

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

4
@ श्राद्ध काव्य। ^ _ ^ मैं सहमत हूँ; जबकि इंटरफेस की लागत कम है, यह अस्तित्वहीन नहीं है। उन्हें लिखने में इतना नहीं, लेकिन डिबगिंग की स्थिति में वास्तविक व्यवहार को प्राप्त करने के लिए यह 1-2 और कदम है, जो कि जब आप अमूर्त के आधा-दर्जन स्तरों को गहराई से प्राप्त करते हैं, तो जल्दी से जोड़ सकते हैं। एक पुस्तकालय में, यह आमतौर पर इसके लायक है। लेकिन एक आवेदन में, समय से पहले सामान्यीकरण की तुलना में रिफैक्टरिंग बेहतर है।
एरोरसट्ज

1

इंटरफेस और अमूर्त कक्षाएं विभिन्न उद्देश्यों की पूर्ति करती हैं:

  • इंटरफेस एपीआई को परिभाषित करते हैं और ग्राहकों के होते हैं जो कार्यान्वयन नहीं करते हैं।
  • यदि कक्षाएं कार्यान्वयन को साझा करती हैं तो आप एक सार वर्ग से लाभान्वित हो सकते हैं ।

आपके उदाहरण में, interface ITypeNameMapperग्राहकों की जरूरतों को परिभाषित करता है और abstract class TypeNameMapperकोई मूल्य नहीं जोड़ रहा है।


2
सार वर्ग भी ग्राहकों के हैं। मुझे नहीं पता कि आपका क्या मतलब है। सब कुछ जो publicक्लाइंट का है। TypeNameMapperबहुत अधिक मूल्य जोड़ रहा है क्योंकि यह कार्यान्वयनकर्ता को कुछ सामान्य तर्क लिखने से बचाता है।
कोनराड

2
एक इंटरफ़ेस के रूप में प्रस्तुत किया गया है interfaceया नहीं, केवल उस सी # में प्रासंगिक है जो पूर्ण एकाधिक उत्तराधिकार के लिए मना करता है।
Deduplicator

0

साझा एपीआई वाले वर्गों के परिवार का समर्थन करने के लिए इंटरफेस की पूरी अवधारणा बनाई गई थी।

यह स्पष्ट रूप से कह रहा है कि इंटरफ़ेस के किसी भी उपयोग का अर्थ है कि इसके विनिर्देश के एक से अधिक कार्यान्वयन के लिए (या होने की उम्मीद है)।

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

प्रश्न में ही उत्तर निहित है। यदि आपके पास एक अमूर्त वर्ग है, तो आप एक सामान्य एपीआई के साथ एक से अधिक व्युत्पन्न वर्ग के निर्माण की तैयारी कर रहे हैं। इस प्रकार, एक इंटरफ़ेस का उपयोग स्पष्ट रूप से इंगित किया गया है।


2
"यदि आपके पास एक सार वर्ग है, ... इंटरफ़ेस का उपयोग स्पष्ट रूप से इंगित किया गया है।" - मेरा निष्कर्ष इसके विपरीत है: यदि आपके पास एक सार वर्ग है, तो इसका उपयोग करें जैसे कि यह एक इंटरफ़ेस था (यदि DI इसके साथ नहीं खेलता है, तो एक अलग कार्यान्वयन पर विचार करें)। केवल जब यह वास्तव में काम नहीं करता है, तो इंटरफ़ेस बनाएं - आप इसे बाद में कभी भी कर सकते हैं।
मातरिनस

1
Ditto, @maaartinus। और यह भी नहीं "... जैसे कि यह एक इंटरफ़ेस था।" एक वर्ग के सार्वजनिक सदस्यों है एक इंटरफेस। "आप इसे कभी भी बाद में कर सकते हैं" के लिए भी डिट्टो; यह डिजाइन फंडामेंटल 101 के दिल में जाता है।
रडार

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

1
@supercat मैं मान सकता था कि आप एक पुस्तकालय लिख रहे हैं। यदि यह एक आवेदन है, तो मैं एक बार में सभी घटनाओं को बदलने में कोई समस्या नहीं देख सकता। मेरा ग्रहण यह कर सकता है (जावा, सी # नहीं), लेकिन अगर ऐसा नहीं हो सकता है, तो यह ठीक है find ... -exec perl -pi -e ...और संभवतः तुच्छ संकलन त्रुटियों को ठीक कर रहा है। मेरी बात यह है कि (वर्तमान में) बेकार चीज न होने का फायदा भविष्य की संभावित बचत से बहुत अधिक है।
मआर्टिनस

पहला वाक्य सही होगा, यदि आपने interfaceकोड के रूप में चिह्नित किया है (आप सी # के बारे में बात कर रहे हैं interface, न कि एक सार इंटरफेस, जैसे कि कक्षाओं / कार्यों / आदि के किसी भी सेट), और इसे समाप्त कर दिया "... लेकिन फिर भी पूर्ण एकाधिक विरासत। " interfaceयदि आपके पास MI है तो s की कोई आवश्यकता नहीं है ।
Deduplicator

0

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

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

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

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


-1

बाकी एप्लिकेशन को जाने बिना उत्तर देना काफी कठिन है।

मान लें कि आप किसी प्रकार के DI मॉडल का उपयोग कर रहे हैं और अपने कोड को जितना संभव हो उतना विस्तारित करने के लिए डिज़ाइन किया है (ताकि आप नया जोड़ सकें TypeNameMapper आसानी से ) मैं हां कहूंगा।

के कारण:

  • आप इसे प्रभावी रूप से मुफ्त में प्राप्त करते हैं, क्योंकि आधार वर्ग interfaceआपको किसी भी बच्चे के कार्यान्वयन में इसके बारे में चिंता करने की आवश्यकता नहीं है
  • अधिकांश IoC फ्रेमवर्क और मॉकिंग लाइब्रेरी interfaceएस की उम्मीद करते हैं । हालांकि उनमें से कई अमूर्त वर्गों के साथ काम करते हैं लेकिन यह हमेशा एक दिया नहीं होता है और मैं लाइब्रेरी के अन्य 99% उपयोगकर्ताओं के समान पथ का अनुसरण करने में बहुत बड़ा विश्वास रखता हूं।

इसके कारण:

  • सख्ती से बोलना (जैसा कि आपने बताया है) आपको वास्तव में जरूरत नहीं है
  • अगर class/ interfaceपरिवर्तन थोड़ा अतिरिक्त उपरि है

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

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