2009-12-16 14 views
12

जब मैंने अमूर्त कक्षाओं के बारे में सीखा तो डब्ल्यूटी (एच *) कहा जाता है !!!एक अमूर्त वर्ग क्या है?

प्रश्न:

  1. एक वर्ग है कि instantiated नहीं किया जा सकता है बनाने की बात क्या है?
  2. कोई भी ऐसी कक्षा क्यों चाहेंगे?
  3. ऐसी स्थिति क्या है जिसमें सार वर्ग आवश्यक हो जाते हैं?

** यदि आप जानते हैं मैं क्या मतलब *

+2

संक्षिप्त उत्तर, विरासत सीखें। – pstanton

+2

@pstanton: मैं क्या कर रहा/करने की कोशिश कर रहा हूँ !!! :- डी –

+4

@pstanton: मैं यह देखने में असफल रहा कि ओपी को उन प्रश्नों से पूछने के लिए कह रहा है जो उन्होंने पहले से ही पूछे हैं, एक जवाब है। –

उत्तर

17
  1. सबसे अधिक (कुछ भाषाओं, एक अलग interface निर्माण है कुछ नहीं) एक आधार स्तरीय या अंतरफलक के रूप में सेवा करने के लिए - कार्यान्वयन (जो उपवर्गों द्वारा प्रदान किया जा रहा है यह पता नहीं है/लागू करने वर्ग)
  2. अमूर्त और फिर से उपयोग
  3. जब आधार स्तरीय एक विधि के लिए कोई सार्थक डिफ़ॉल्ट कार्यान्वयन प्रदान कर सकते हैं (लेकिन उपवर्गों कार्यान्वयन के गैर सार भागों फिर से उपयोग करने की अनुमति, किसी भी क्षेत्र, गैर-अमूर्त तरीकों, आदि)

उदाहरण के लिए:

public abstract class Stream { /* lots of code, some abstract methods */ } 

क्या बिल्ली खुद द्वारा एक धारा है? क्या धारा धारा का? एक फाइल के लिए एक धारा? एक नेटवर्क? एक मेमोरी बफर? प्रत्येक के पास पढ़ने/लिखने के अलग-अलग और असंबंधित तरीके हो सकते हैं, लेकिन एक आम एपीआई प्रदान करते हैं। यह बनाता है कोई मतलब नहींसिर्फ एक Stream बनाने के लिए है, लेकिन abstract वर्ग के माध्यम से, आप कर सकते हैं कोड विवरण जानने के बिना Stream एपीआई के:

Stream s = CreateStream(...); // I don't *care* what kind of stream 
s.Write(new byte[] {1,2,3,4,5}); 
s.Close(); 
+0

लेकिन क्या आपने यहां "स्ट्रीम एस" लिखकर एक उदाहरण नहीं बनाया है ?? मैं अभी भी बहुत उलझन में हूं .. –

+0

नहीं, यह एक चर घोषित करता है जो स्ट्रीम धारण कर सकता है। वास्तविक निर्माण 'CreateStream() 'में कहीं होता है - यह कॉल के माध्यम से' नई फ़ाइलस्ट्रीम() ', या' नई मेमोरीस्ट्रीम 'तक हो सकता है, या यह पहले से बनाई गई स्ट्रीम को वापस कर सकता है। मुद्दा यह है कि, आपको परवाह नहीं है कि यह किस प्रकार की धारा है, बस यह 'स्ट्रीम' है, और इसलिए आप उस पर 'स्ट्रीम' के उदाहरण विधियों को कॉल कर सकते हैं। –

+0

क्या यह बेस क्लास कन्स्ट्रक्टर को कॉल नहीं करता है? या अमूर्त वर्ग में कोई कन्स्ट्रक्टर नहीं है? –

2

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

2

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

7

सार (आधार) कक्षाएं आपको कक्षा के पदानुक्रम को लागू करने के लिए अर्ध-ठोस वर्ग प्रदान करती हैं।वे आपको कई कार्य कर सकते हैं:

  1. समेकित सामान्य व्यवहार (एक अंतरफलक जो केवल अनुबंध को परिभाषित करता है के विपरीत)
  2. कार्यों
  3. प्रदान करें अच्छी तरह से परिभाषित शाखा अंक के लिए डिफ़ॉल्ट प्रदान करें (और वैकल्पिक ओवरराइड करने योग्य) कार्यान्वयन विरासत के लिए
  4. नियंत्रण आईओसी इंजेक्शन अंक

सूची पर चला जाता है पदानुक्रम।

+0

घोषित करते समय अमूर्त कीवर्ड के उपयोग के कारण आईओसी इंजेक्शन बिंदु क्या है? –

+0

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

+1

नियंत्रण में उलटा - कोड _you_ लिखने के लिए एक शब्द सभी काम नहीं करता है, लेकिन कुछ "जादुई" आपके नियंत्रण से बाहर होता है। ऑब्जेक्ट "कहीं नहीं" से बाहर दिखाई देते हैं और आपके चर को सौंपा गया है या कन्स्ट्रक्टर के पैरामीटर के रूप में पास किया गया है। यह आपके कोड से बचने के लिए बहुत आसान हो जाता है यह जानकर कि यह एक वेब कंटेनर के अंदर चल रहा है और इसे डेटाबेस कनेक्शन प्राप्त करने के लिए FooBar को कॉल करने की आवश्यकता है। –

1

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

एक अमूर्त कीबोर्ड, मॉनीटर या सेल फोन की तरह है। सभी कीबोर्ड में डेटा दर्ज करने की क्षमता होती है; सभी मॉनीटरों में पिक्सल प्रदर्शित करने की क्षमता होती है; और सभी सेल फोन में कॉल करने की क्षमता होती है। लेकिन इन वस्तुओं के निर्माताओं के व्यवहार को लागू करने के विभिन्न तरीके हैं।

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

एक सेल फोन एक सेल फोन है, और एक अमूर्त वर्ग के उपवर्गों सभी सार वर्ग हैं।

+0

कम से कम .NET parlance में, यह एक इंटरफ़ेस का वर्णन करता है, एक अमूर्त वर्ग नहीं। –

5

1) कक्षा बनाने का क्या मतलब है जिसे तत्काल किया जा सकता है?

सिर्फ इसलिए कि कुछ तुरंत तत्काल नहीं है इसका मतलब यह नहीं है कि यह उपयोगी है। एक अमूर्त वर्ग विरासत में एक महत्वपूर्ण भूमिका निभाता है और इसके विरासत वर्गों के वर्ग डिजाइन में बहुत उपयोगी हो सकता है।

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

यह आपको जो भी करने की अनुमति देता है वह एक साथ विरासत विरासत वर्ग है जिसका अर्थ है कि आप मान सकते हैं कि अमूर्त वर्ग में परिभाषित कुछ विधियां विरासत कक्षाओं में मौजूद होंगी - जो उपयोगी हो सकती हैं।

2) क्यों किसी को भी चाहेगा इस तरह के एक वर्ग

आमतौर पर मैं यह सुनिश्चित करना कि विरासत में मिला वर्गों की एक श्रृंखला कुछ तरीकों आदि मेरे लिए है यह एक सेट की एक संरचना के डिजाइन के लिए वास्तव में उपयोगी है के लिए इसका इस्तेमाल करते हैं विरासत कक्षाओं के।

3) ऐसी स्थिति क्या है जिसमें सार वर्ग आवश्यक हो?

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

0

ठीक है, अब आपने प्रत्येक कार्यान्वयन में सभी विधियों के साथ एक इंटरफ़ेस बनाया है। जैसे ही आप प्रोग्राम करते हैं, आप देखते हैं कि कुछ कोड ब्लॉक इंटरफ़ेस के सभी कार्यान्वयन द्वारा साझा किए जाते हैं।

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

यह केवल सार है क्योंकि आप सभी उत्तराधिकारी वर्गों को अपने स्वयं के कार्यान्वयन चाहते हैं।

1

एक अमूर्त वर्ग वह है जिसे तत्काल नहीं किया जा सकता है। उदाहरण के लिए, एक स्क्वायर, सर्किल, या आयताकार एक प्रकार का आकार है और इसे कक्षा आकार से लिया जा सकता है।

एक आकार में स्क्वायर, सर्कल, या आयताकार के समान कोड होगा जो आकार के क्षेत्र की गणना करता है। लेकिन एक आकार को तत्काल करना बेकार होगा क्योंकि यह एक अमूर्त अवधारणा है और वर्ग, मंडल, और आयताकार वास्तविक संस्थाएं हैं।

1

एक अमूर्त वर्ग का बिंदु कार्यान्वयन का वर्णन किए बिना, आपके इंटरफ़ेस को परिभाषित (प्रतिबंधित) करना है।

  1. एक सार वर्ग को एक व्युत्पन्न वर्ग प्रकार के साथ एक संगत वस्तु का निर्माण करके तत्काल किया जा सकता है।

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

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

0

सार कक्षाएं एक वर्ग बनाने में सक्षम होने के द्वारा एक उपयोगी उद्देश्य प्रदान करती हैं जो कुछ ठोस के बजाय अवधारणा का प्रतीक बनती है। उदा, पशु एक वर्ग हो सकता है, लेकिन कोई भी बस एक जानवर, यह या तो एक बर्ड, कुत्ता, या बिल्ली आदि जो जानवरों के विभिन्न प्रकार के कर रहे हैं। उम्मीद है की यह मदद करेगा। यह विरासत और बहुरूपता जैसी अवधारणाओं के संयोजन के साथ भी जाता है।

2

यह केवल उपभोक्ता से वास्तविक कार्यान्वयन को छिपाने के लिए है जो इसे उपभोग करता है।

  • यह विशेष कार्यों के लिए concerete कार्यान्वयन प्रदान करता है और यह सीधे
  • यह instantiated नहीं किया जा सकता है केवल कक्षाएं उन लागू कर रहे हैं से पहुँचा जा जाएगा।
  • इसलिए व्युत्पन्न वर्ग का उपभोग करने वाले ग्राहक, कभी भी कार्यक्षमता के कार्यान्वयन को नहीं जानते हैं क्योंकि इसका abstratced है।

अब आप पूछेंगे कि हमें इसकी आवश्यकता क्यों है, क्योंकि इंटरफेस एक ही तंत्र की सेवा करते हैं ..सरल लकड़हारा उदाहरण

interface ILogger 
{ 
    string PrepareLog(System.Exception ex); 
    void InitializeLogger(string Type); 
    int WriteLog(string msg); 
} 

किसी भी प्रवेश ग्राहक को लागू करता है इस इंटरफेस यह सब कार्यक्षमता

class EventLogger : ILogger 
{ 
    public override void InitializeLogger(string Type) 
    { 
     //Event Logger Initialize 
    } 
    public override int WriteLog(string msg) 
    { 
     //Write to event log 
     return 1; 
    } 
    public override string PrepareLog(System.Exception ex) 
    { 
     return ex.StackTrace ; 
    } 
} 

class FileLogger : ILogger 
{ 
    public override void InitializeLogger(string Type) 
    { 

    } 
    public override int WriteLog(string msg) 
    { 
     //Write to File 
     return 1; 
    } 
    public override string PrepareLog(System.Exception ex) 
    { 
     return ex.StackTrace ; 
    } 
} 


class MailLogger : ILogger 
{ 
    public override void InitializeLogger(string Type) 
    { 

    } 
    public override int WriteLog(string msg) 
    { 
     //Write to mail 
     return 1; 
    } 

    public override string PrepareLog(System.Exception ex) 
    { 
     //prepare HTML Formatted msg 
     return ex.StackTrace ; 
    } 
} 

को लागू करना चाहिए और कक्षाओं EventLogger, FileLogger और maillogger लागू करता iLogger के माध्यम से जाओ और संदर्भ विशिष्ट कार्यान्वयन देता है । अब हम PrepareLog के वास्तविक कार्यान्वयन को छिपाना चाहते थे और यह अपवाद ऑब्जेक्ट से लॉग संदेश तैयार करने का सामान्य संचालन करेगा।

हमारे वर्तमान कार्यान्वयन में हमारे पास एक विधि को ठोस बनाने और दूसरों को सिर्फ अनुबंध होने का विकल्प नहीं है।

तो सार कक्षाएं

abstract class AbstractLogger:ILogger 
{ 
    #region ILogger Members 

    public virtual string PrepareLog(System.Exception ex) 
    { 
     return ex.StackTrace; 
    } 

    public abstract void InitializeLogger(string Type); 
    public abstract int WriteLog(string msg); 

    #endregion 
} 


class EventLogger : AbstractLogger 
{ 
    public override void InitializeLogger(string Type) 
    { 
     //Event Logger Initialize 
    } 
    public override int WriteLog(string msg) 
    { 
     //Write to event log 
     return 1; 
    } 
} 

class FileLogger : AbstractLogger 
{ 
    public override void InitializeLogger(string Type) 
    { 

    } 
    public override int WriteLog(string msg) 
    { 
     //Write to File 
     return 1; 
    } 
} 

class DBLogger : AbstractLogger 
{ 
    public override void InitializeLogger(string Type) 
    { 

    } 
    public override int WriteLog(string msg) 
    { 
     //Write to DB 
     return 1; 
    } 
} 

class MailLogger : AbstractLogger 
{ 
    public override void InitializeLogger(string Type) 
    { 

    } 
    public override int WriteLog(string msg) 
    { 
     //Write to mail 
     return 1; 
    } 

    public override string PrepareLog(System.Exception ex) 
    { 
     //prepare HTML Formatted msg 
     return ex.StackTrace ; 
    } 
} 

अब मैं AbstractLogger वर्ग जो iLogger से विरासत और अकेले लागू किया PrepareLog विधि बनाया है साथ कार्यान्वयन थोड़ा परिवर्तित करने देता है, remainig तरीकों सार छोड़ दिया है। इसलिए उपभोक्ता उनके कार्यान्वयन में संदर्भ विशिष्ट कोड लिखेंगे।

तो अब किसी भी लॉगर्स को शुरू करने वाले कोसमर्स से प्रीपेरलॉग विधि पूरी तरह छिपी हुई (लॉग तैयारी का अर्थ)।

तो क्यों PrepareLog वर्चुअल एड है ??

ऐसे परिदृश्य हैं जो उपभोक्ता तैयार करने की विधि को ओवरराइड करना चाहते हैं, पूर्व: मेललॉगर प्रीपेरलॉग को ओवरराइड करेगा और मेल संदेशों को आपूर्ति करने के लिए HTML प्रारूपित आउटपुट प्रारूपित करेगा।

1

दोनों इंटरफेस और अमूर्त वर्ग आपके कोड बेस में ढीले युग्मन को बढ़ावा देते हैं। सार वर्ग इंटरफेस और कंक्रीट कक्षाओं के बीच एक समझौता है, क्योंकि अमूर्त कक्षाओं में कार्यान्वित व्यवहार के साथ वास्तविक विधियां हो सकती हैं।

सामान्य रूप से, इंटरफेस पसंद करते हैं। सार कक्षाएं तब उपयोगी होती हैं जब आपके पास विरासत का पेड़ होता है जिसमें बाल वर्गों द्वारा उपयोग किए जाने वाले सामान्य संचालन होते हैं। लेकिन यहां तक ​​कि आप यहां घोषित करना चाहते हैं कि आपकी अमूर्त कक्षा एक इंटरफ़ेस लागू करती है। Josh Bloch इसे "सार इंटरफेस" पैटर्न कहते हैं। यह आपको अमूर्त वर्ग के विभिन्न कार्यान्वयन को तैनात करने की अनुमति देता है, जो विरोधाभासी रूप से वास्तव में पूरी तरह सार नहीं है - केवल इंटरफेस हैं।

0

इंटरफेस के साथ के रूप में एक ही, एक अमूर्त वर्ग एक अनुबंध जिसमें आप कुछ सामान्य (या सार) कार्यक्षमता है कि कई स्थितियों के लिए लागू है प्रदान की है, लेकिन यह विशिष्ट है कुछ सुविधा प्रदान करने के लिए एक implementer उम्मीद और/या प्रत्येक परिदृश्य के लिए अलग। किसी ने Stream उदाहरण का उल्लेख किया - बहुत अच्छा उदाहरण।

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