ऑब्जेक्ट ओरिएंटेड प्रोग्रामिंग: गेटर्स / सेटर या लॉजिकल नाम


12

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

मैं एक वर्ग मिल गया है CharacterStylesजो सदस्य चर है bold, italic, underline(और कुछ अन्य, लेकिन मैं इसे सरल रखने के लिए उन्हें बाहर छोड़ देंगे)। कार्यक्रम के अन्य हिस्सों को इन चरों तक पहुंचने की अनुमति देने का सबसे आसान तरीका, गेट्टर / सेटर विधियों को लिखना होगा, ताकि आप कर सकें styles.setBold(true)और styles.setItalic(false)

लेकिन मुझे यह पसंद नहीं है। केवल इसलिए नहीं कि बहुत सारे लोग कहते हैं कि गेटर्स / सेटर इनकैप्सुलेशन को तोड़ते हैं (क्या यह वास्तव में इतना बुरा है?), लेकिन ज्यादातर इसलिए कि यह मुझे तर्कसंगत नहीं लगता। मैं एक विधि के माध्यम से एक चरित्र की शैली की अपेक्षा करता हूं, styles.format("bold", true)या ऐसा कुछ, लेकिन इन सभी विधियों के माध्यम से नहीं।

हालांकि एक समस्या है। चूँकि आप C ++ में स्ट्रिंग के कंटेंट द्वारा ऑब्जेक्ट मेंबर वेरिएबल को एक्सेस नहीं कर सकते, इसलिए मुझे या तो सभी शैलियों के लिए एक बड़ा इफ-स्टेटमेंट / स्विच कंटेनर लिखना होगा, या मुझे शैलियों को एक सहयोगी सरणी में स्टोर करना होगा ( नक्शा)।

मैं समझ नहीं पा रहा हूं कि सबसे अच्छा तरीका क्या है। एक पल मुझे लगता है कि मुझे गेटर्स / सेटर लिखना चाहिए और अगले ही पल मैं दूसरे रास्ते की ओर झुक गया। मेरा सवाल है: आप क्या करेंगे? और आप ऐसा क्यों करेंगे?


क्या वास्तव में चरित्र वर्ग तीन बंडल के अलावा कुछ भी नहीं करता है? इसका सेवन कैसे किया जाता है?
मार्क कान्स

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

आप विभिन्न शैली विकल्पों को परिभाषित करने के लिए एक एनम का उपयोग कर सकते हैं, फिर एक स्विच स्टेटमेंट का उपयोग कर सकते हैं। Btw, आप कैसे अपरिभाषित हैं?
तियाना

@ ध्यान: वास्तव में, मैंने भी एक एनम का उपयोग करने के बारे में सोचा था, लेकिन यह सिर्फ एक मामूली विवरण है। मैं NULL को अपरिभाषित मान सेट करने की योजना बना रहा था। यह सबसे अच्छा तरीका नहीं है?
मेंढक

जवाबों:


6

हां, गेटर्स / सेटर इनकैप्सुलेशन को तोड़ते हैं - वे मूल रूप से अंतर्निहित क्षेत्र तक सीधे पहुंचने के बीच सिर्फ एक अतिरिक्त परत हैं। आप सीधे इसे एक्सेस कर सकते हैं।

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

DrDobbs के पास एक लेख है जो अधिक कहता है।

आपकी समस्या के लिए, मेरे पास 2 विधियाँ होंगी सेटिसल और क्लियरसेटल (या जो भी) जो संभव शैलियों की एक सूची ले। इन विधियों के अंदर एक स्विच स्टेटमेंट तब संबंधित मानों को उपयुक्त वर्ग चर पर लागू करेगा। इस तरह, आप शैलियों के आंतरिक प्रतिनिधित्व को कुछ और में बदल सकते हैं यदि आप बाद में उन्हें एक स्ट्रिंग के रूप में संग्रहीत करने का निर्णय लेते हैं (उदाहरण के लिए HTML में उपयोग के लिए) - ऐसा कुछ जिसे आपके वर्ग के सभी उपयोगकर्ताओं को बदलने की आवश्यकता होगी यदि आप उपयोग करते हैं गुण प्राप्त / सेट करें।

यदि आप मनमाना मूल्य लेना चाहते हैं, तो आप अभी भी स्ट्रिंग्स पर स्विच कर सकते हैं, या तो एक बड़ा इफ -स्टेटमेंट है (यदि उनमें से कुछ है), या स्ट्रिंग मानों का एक नक्शा std का उपयोग करके विधि संकेत करने के लिए :: mem_fun (या std :: फ़ंक्शन ) इसलिए "बोल्ड" को एक मानचित्र कुंजी में संग्रहीत किया जाएगा, जिसका मान sts :: mem_fun एक विधि से है जो वेरिएबल को सही पर सेट करता है (यदि स्ट्रिंग्स सदस्य चर नामों के समान हैं, तो आप भी उपयोग कर सकते हैं stringifying मैक्रो कोड की राशि है जो आप लिखने की जरूरत को कम करने के लिए)


बहुत बढ़िया जवाब! विशेष रूप से HTML को डेटा स्टोर करने के बारे में भाग ने मुझे इस सड़क पर वास्तव में नीचे जाने के लिए एक अच्छे कारण के रूप में मारा। तो आप सुझाव देंगे कि अलग-अलग शैलियों को एक एनम में संग्रहीत करें और फिर शैलियों को सेट करें styles.setStyle(BOLD, true)? क्या वो सही है?
मेंढक

हाँ, केवल मेरे पास 2 विधियाँ होंगी - setStyle (BOLD) और क्लियरस्टाइल (BOLD)। 2 पैरामीटर को भूल जाओ, मैं सिर्फ इसे पसंद करता हूं और आप सभी स्टाइल झंडे को साफ करने के लिए कोई पैरामीटर नहीं लेने के लिए क्लियरटाइल को अधिभार कर सकते हैं।
gbjbaanb 13

यह काम नहीं करेगा, क्योंकि कुछ प्रकार (जैसे फ़ॉन्ट-आकार) को एक पैरामीटर की आवश्यकता होती है। लेकिन अभी भी उत्तर के लिए धन्यवाद!
मेंढक

मैं इसे लागू करने की कोशिश कर रहा हूं, लेकिन एक समस्या है जिस पर मैंने विचार नहीं किया: आप कैसे लागू styles.getStyle(BOLD)करते हैं जब आपके पास न केवल प्रकार के बूलियन के सदस्य चर होते हैं, बल्कि प्रकार के पूर्णांक और स्ट्रिंग भी होते हैं (उदाहरण के लिए:) styles.getStyle(FONTSIZE)। चूंकि आप रिटर्न प्रकार अधिभार नहीं लगा सकते हैं, आप इसे कैसे प्रोग्राम करते हैं? मुझे पता है कि आप शून्य बिंदुओं का उपयोग कर सकते हैं, लेकिन यह मेरे लिए बहुत बुरा तरीका है। क्या आपके पास ऐसा करने के लिए कोई संकेत है?
मेंढक

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

11

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

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

एक छद्मकोड उदाहरण के लिए:

class TextWriter : TextDrawingInterface {
    public:
        void WriteString(string x) {
            // write some text somewhere somehow
        }
}

class BoldDecorator : TextDrawingInterface {
    public:
        void WriteString(string x) {
            // bold application on
            m_textWriter.WriteString(x);
            // bold application off
        }

        ctor (TextDrawingInterface textWriter) {
            m_textWriter = textWriter;
        }

    private:
        TextWriter m_TextWriter;
}

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

TextDrawingInterface GetDecoratedTextWriter() {
    return new BoldDecorator(new ItalicDecorator(new TextWriter()));
}

और कोड जो इस विधि को कॉल करता है, उसे यह जानने की आवश्यकता नहीं है कि यह क्या प्राप्त कर रहा है। जब तक यह SOMETHING है कि एक WriteString विधि के माध्यम से पाठ आकर्षित कर सकते हैं।


हम्म, मैं कल उस पर नए सिरे से विचार करने जा रहा हूं और फिर आपके पास वापस आऊंगा। जवाब के लिए धन्यवाद।
मेंढक

मैं डेकोरेटर पैटर्न का बहुत बड़ा प्रशंसक हूं। तथ्य यह है कि यह पैटर्न HTML जैसा दिखता है (जहां कोर ऑपरेशन को टैग के साथ इनपुट स्ट्रिंग को संलग्न करना है) एक प्रमाण है कि यह दृष्टिकोण आपके इंटरफ़ेस उपयोगकर्ता की सभी जरूरतों को पूरा कर सकता है। एक बात ध्यान में रखना है कि एक इंटरफ़ेस जो अच्छा और आसान उपयोग है, एक अंतर्निहित कार्यान्वयन हो सकता है जो तकनीकी रूप से जटिल है। उदाहरण के लिए, यदि आप वास्तव में स्वयं टेक्स्ट रेंडरर को लागू कर रहे हैं, तो आप पा सकते हैं कि काम TextWriterपूरा करने के लिए ( BoldDecoratorऔर ItalicDecoratorसीधे-सीधे) दोनों से बात करनी होगी ।
1

हालांकि यह एक अच्छा जवाब है, क्या यह ऑप के प्रश्न को फिर से पेश नहीं करता है? "बोल्ड ऐपेटन ऑन" -> यह कैसे होने जा रहा है? SetBold () की तरह बसने / पाने वालों का उपयोग करना? जो बिल्कुल op का सवाल है।
stijn

1
@stijn: वास्तव में नहीं। उस स्थिति से बचने के कई तरीके हैं। उदाहरण के लिए, आप एक बिल्डर में एक टॉगल स्टाइल विधि (एनम तर्क) के साथ लपेट सकते हैं जो एक सरणी से डेकोरेटर्स को जोड़ता है और हटाता है, केवल अंतिम आइटम को सजाने पर जब आप BuildDecoratedTextWriter कहते हैं। या आप सुझाए गए आधार के रूप में कर सकते हैं और आधार वर्ग को जटिल बना सकते हैं। परिस्थिति और ओपी पर निर्भर करता है कि समग्र अनुमान के बारे में पर्याप्त नहीं था कि वह उसके लिए सबसे अच्छा है। वह काफी स्मार्ट लगता है, हालांकि वह पैटर्न मिलते ही इसका पता लगा सकता है।
पीडीआर

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

0

मैं दूसरे समाधान की ओर झुक गया। यह अधिक सुरुचिपूर्ण और लचीला दिखता है। यद्यपि बोल्ड, इटैलिक और अंडरलाइन (ओवरलाइन?) के अलावा अन्य प्रकारों की कल्पना करना मुश्किल है, लेकिन सदस्य चर का उपयोग करके नए प्रकार जोड़ना मुश्किल होगा।

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


1
इन प्रकारों के अलावा मैं स्ट्राइकथ्रू, फ़ॉन्ट-आकार, फ़ॉन्ट-परिवार, सुपरस्क्रिप्ट, सबस्क्रिप्ट, और शायद अन्य को बाद में जोड़ूंगा। लेकिन आपने अपने प्रोजेक्ट में उस तरीके को क्यों चुना? क्या आपको नहीं लगता कि अनुमत विशेषताओं की सूची को संग्रहित करना गंदा कोड है? मैं वास्तव में उत्सुक हूं कि इन सवालों के आपके जवाब क्या हैं!
मेंढक

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

लेकिन मेरे ग्राहक को कस्टम विशेषताएँ जोड़ने की आवश्यकता नहीं होगी। और उस मामले में मुझे लगता है कि यह थोड़ा "हैकी" लगता है। क्या आप सहमत नहीं हैं?
मेंढक

यदि आपको डायनेमिक नंबर की विशेषताओं का सामना नहीं करना पड़ता है तो आपको उन्हें स्टोर करने के लिए लचीले स्थान की आवश्यकता नहीं है। यह सच है :) मैं हालांकि दूसरे भाग से सहमत नहीं हूं। एक शब्दकोश / हैशमैप / इत्यादि में स्ट्रिंग विशेषताएँ मेरे विचार में एक बुरा दृष्टिकोण नहीं है।
आंद्रेजेज बोबाक

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