2012-12-03 30 views
6

मैंने इस समस्या का हल ढूंढने के लिए अभी कुछ देखा है। मैंने कई तरीकों को हल किया जो इसे हल कर सकते थे लेकिन ईमानदार होने के लिए मुझे एहसास नहीं हुआ कि किस तरह से इसे "सही" सी # या ओओपी तरीका हल करने का तरीका माना जाएगा। मेरा लक्ष्य न केवल समस्याओं को हल करने के लिए बल्कि कोड मानकों का एक अच्छा सेट विकसित करने के लिए है और मुझे पूरा यकीन है कि इस समस्या को संभालने का एक मानक तरीका है।सी # एक सूची में विभिन्न वर्ग वस्तुओं

मान लें कि मेरे पास अपने संबंधित वर्गों और संचार के तरीकों के साथ 2 प्रकार के प्रिंटर हार्डवेयर हैं: प्रिंटर टाइप 1, प्रिंटर टाइप 2।

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

हालांकि मैं उन सभी प्रिंटरों की एक सूची को लागू करना चाहता हूं और सूची के बिना जाने और सभी प्रिंटर पर "भेजें (स्ट्रिंग संदेश)" के रूप में काम करने में सक्षम होना चाहूंगा। मैं "प्रिंटरलिस्ट [0] नाम" जैसे चरों तक पहुंचना चाहूंगा जो दोनों ऑब्जेक्ट्स के लिए समान हैं, हालांकि मैं कुछ स्थानों पर भी ऑब्जेक्ट के लिए विशिष्ट डेटा तक पहुंचना चाहता हूं (उदाहरण के लिए सेटिंग विंडो में वह एप्लिकेशन जहां COM-port नाम एक ऑब्जेक्ट के लिए सेट किया गया है और दूसरे के लिए आईपी/पोर्ट नंबर)।

तो, कम कुछ की तरह में:

आम में:

  • नाम
  • संदेश()

विशिष्ट PrinterType1 रहे हैं:

  • पोर्ट

विशिष्ट PrinterType2 रहे हैं:

  • आईपी

और मैं करने के लिए, उदाहरण के लिए,() सभी वस्तुओं पर ध्यान दिए बिना प्रकार और वर्तमान ऑब्जेक्ट की संख्या का भेजें करते कामना करते हैं।

मैंने पॉलिमॉर्फिज्म, जेनेरिक, इंटरफेस और इस तरह के बारे में पढ़ा है, लेकिन मैं जानना चाहता हूं कि यह कैसे मेरी आंखों में बुनियादी है, समस्या आम तौर पर सी # (और/या सामान्य रूप से ओओपी) में निपटाई जाएगी।

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

मैं किसी भी उत्तर के लिए वास्तव में आभारी हूं। यहां के लोग बहुत जानकार लगते हैं और इस जगह ने मुझे पहले कई समाधान प्रदान किए हैं। अब मेरे पास जवाब देने और वोट देने के लिए एक खाता है।

संपादित करें:

इसके अतिरिक्त, समझाने मैं भी वास्तविक printertype की वस्तुओं का उपयोग करने में सक्षम होना चाहते हैं करने के लिए। उदाहरण के लिए प्रिंटर टाइप 1 में पोर्ट वैरिएबल जो एक सीरियलपोर्ट ऑब्जेक्ट है। मैं इसे एक्सेस करना चाहता हूं: PrinterList[0].Port.Open()

और अंडरलेइंग पोर्ट की कार्यक्षमता की पूरी श्रृंखला तक पहुंच प्राप्त करना चाहूंगा।

foreach (printer in Printers) 
    printer.Send(message) 
+0

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

+0

+1। कोड मानकों का एक अच्छा सेट विकसित करना चाहते हैं। –

उत्तर

9

इंटरफेस का उपयोग करते हुए एक छद्म उदाहरण।

public interface IPrinter 
{ 
    void Send(); 
    string Name { get; } 
} 

public class PrinterType1 : IPrinter 
{ 
    public void Send() { /* send logic here */ } 
    public string Name { get { return "PrinterType1"; } } 
} 

public class PrinterType2 : IPrinter 
{ 
    public void Send() { /* send logic here */ } 
    public string Name { get { return "Printertype2"; } } 

    public string IP { get { return "10.1.1.1"; } } 
} 


// ... 
// then to use it 
var printers = new List<IPrinter>(); 

printers.Add(new PrinterType1()); 
printers.Add(new PrinterType2()); 

foreach(var p in printers) 
{ 
    p.Send(); 

    var p2 = p as PrinterType2; 

    if(p2 != null) // it's a PrinterType2... cast succeeded 
    Console.WriteLine(p2.IP); 
} 
+0

बहुत अच्छे और तेज़ सुझाव के लिए धन्यवाद। आइए मान लें कि प्रिंटर टाइप 2 में परिभाषित आईपी वैरिएबल एक सीरियलपोर्ट पोर्ट ऑब्जेक्ट था जिसे मैं संपादित करना चाहता हूं, क्या मैं इसे सीधे एक्सेस कर सकता हूं? Port.Dispose(), Port.Name(), Port.Open(), आदि –

+0

इंटरफ़ेस केवल उन विधियों/गुणों का खुलासा करता है जो यह घोषित करता है। यदि आपके पास आईप्रिंटर ऑब्जेक्ट्स का संग्रह है, तो आपको यह निर्धारित करना होगा कि एक विशिष्ट उदाहरण वास्तव में प्रिंटर टाइप 2 का उदाहरण था और फिर इसे उचित रूप से डाला गया था। (यह ** ** ** ** ** ** ऑपरेटरों के रूप में किया जा सकता है।) – ThatBlairGuy

+0

इसलिए, यदि एक वर्ग में पोर्ट ऑब्जेक्ट है और कोई नहीं है और मैं 2 ऑब्जेक्ट्स के साथ एक सूची भरता हूं: प्रिंटर टाइप 1 और प्रिंटर टाइप 2 में से एक। उनमें से केवल एक "पोर्ट" ऑब्जेक्ट है। मैं इसे कैसे एक्सेस कर सकता हूं? मुझे यहां कुछ याद आ रही है, लेकिन उपर्युक्त कोड में, मैं नहीं देख सकता कि मैं किसी ऑब्जेक्ट को कैसे एक्सेस करता हूं जो केवल दो वर्गों में से एक में मौजूद है। क्या आप कह रहे हैं कि मुझे सूची सदस्य के प्रकार की जांच करने की आवश्यकता है, इसे वास्तव में उस प्रकार के रूप में डालें (या जब मैंने इसे सूची में जोड़ा था) और वहां से वास्तविक अंतर्निहित वस्तु को एक्सेस और संपादित किया गया था? –

2

एक अंतरफलक बनाएं (माना IPrinterType) है कि अपने "आम" तरीकों और रखती है: एक ही समय में मैं सामान्य कार्यों कि विभिन्न वस्तुओं के लिए एक ही तरह से काम करते हैं (लेकिन अलग कार्यान्वयन के साथ) कॉल करना चाहते हैं इसके बजाय इस इंटरफ़ेस का उपयोग करें।

+0

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

0

आपका वर्णन क्या है, जहां इंटरफेस के लिए डिजाइन किया गया है। उसमें सभी सामान्य गुण/विधियों को रखें और ठोस कार्यान्वयन को छुपाएं। मैं अभी भी आधार Printer कक्षा रखने की अनुशंसा करता हूं क्योंकि स्पष्ट रूप से समान कोड होगा जिसे साझा किया जा सकता है।

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

abstract class Printer 
{ 
    public string Name { get; set; } 
    public abstract string Send(string Message); 
} 

तब आप उस वर्ग से विरासत को मनचाहे तरीके से अपने संदेश() फ़ंक्शन को लागू:

+0

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

+0

@jeah_wicer तो यह एक परिदृश्य है जहां आपको इसे उस विशेष व्युत्पन्न प्रकार पर डालना होगा उदा। 'var castedObj = यह DerivedType के रूप में; अगर (castedObj! = null) {...} '। – James

2

क्या आप देख रहे हैं एक सार आधार वर्ग है, इसलिए की तरह है।

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

1

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

बेस क्लास में इसे लागू करने की वास्तव में कोई आवश्यकता नहीं है।

यदि आपकी बेस क्लास एक अमूर्त वर्ग है, तो आप इसे केवल घोषित कर सकते हैं और फिर इसे लागू करने के लिए ठोस कक्षाओं में छोड़ सकते हैं।

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

संबंधित मुद्दे