क्या मुझे हमेशा एक आंतरिक डेटा संरचना को पूरी तरह से अलग करना चाहिए?


11

कृपया इस वर्ग पर विचार करें:

class ClassA{

    private Thing[] things; // stores data

    // stuff omitted

    public Thing[] getThings(){
        return things;
    }

}

यह वर्ग उस सरणी को उजागर करता है जिसका उपयोग वह डेटा संग्रहीत करने के लिए करता है, जो किसी भी ग्राहक कोड में रुचि रखता है।

मैंने ऐसा ऐप में किया था, जिस पर मैं काम कर रहा हूं। मेरे पास एक ChordProgressionवर्ग था जो Chordएस के अनुक्रम को संग्रहीत करता है (और कुछ अन्य चीजें करता है)। इसमें एक Chord[] getChords()विधि थी जो जीवा के सरणी को लौटाती थी। जब डेटा संरचना को बदलना था (एक सरणी से एक ArrayList के लिए), तो सभी क्लाइंट कोड टूट गए।

इससे मुझे लगा - शायद निम्नलिखित दृष्टिकोण बेहतर है:

class ClassA{

    private Thing[] things; // stores data

    // stuff omitted

    public Thing[] getThing(int index){
        return things[index];
    }

    public int getDataSize(){
        return things.length;
    }

    public void setThing(int index, Thing thing){
        things[index] = thing;
    }

}

डेटा संरचना को स्वयं उजागर करने के बजाय, डेटा संरचना द्वारा प्रस्तुत किए गए सभी ऑपरेशनों को अब सीधे वर्ग द्वारा इसे घेरने की पेशकश की जाती है, सार्वजनिक तरीकों का उपयोग करके जो डेटा संरचना को सौंपते हैं।

जब डेटा संरचना बदल जाती है, तो केवल इन विधियों को बदलना पड़ता है - लेकिन वे करने के बाद, सभी क्लाइंट कोड अभी भी काम करते हैं।

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


क्या यह दृष्टिकोण आम है? आप इस बारे में क्या सोचते है? यह अन्य क्या है? क्या केवल आंतरिक डेटा संरचना को सौंपने के लिए कम से कम तीन सार्वजनिक तरीकों को लागू करना उचित है?

जवाबों:


14

जैसे कोड:

   public Thing[] getThings(){
        return things;
    }

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

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

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

केवल नकारात्मक पक्ष मैं आपके प्रस्ताव में यह देख सकता हूं कि कोड को और अधिक काम करना है (और अब आप अपने उपभोक्ता वर्गों को फिर से कोड करने जा रहे हैं - लेकिन आपको वैसे भी ऐसा करना होगा।) लेकिन यह वास्तव में नकारात्मक पक्ष नहीं है। - आपको इसे सही तरीके से करने की आवश्यकता है, और कभी-कभी यह अधिक काम लेता है।

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

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

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

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


1
जवाब के लिए धन्यवाद। एक प्रश्न: क्या होगा अगर आंतरिक डेटा संरचना में, शायद, 5 सार्वजनिक तरीके हैं - जो कि मेरी कक्षा के सार्वजनिक इंटरफ़ेस द्वारा चित्रित किए जाने की आवश्यकता है? उदाहरण के लिए, एक जावा ArrayList निम्न विधियों है: get(index), add(), size(), remove(index), और remove(Object)। प्रस्तावित तकनीक का उपयोग करते हुए, इस ArrayList वाले वर्ग में आंतरिक संग्रह को सौंपने के लिए पांच सार्वजनिक तरीके होने चाहिए। और कार्यक्रम में इस वर्ग का उद्देश्य सबसे अधिक इस ArrayList को इनकैप्सुलेट नहीं करना है, बल्कि कुछ और करना है। ArrayList एक विस्तार है। [...]
अवीव कोहन २ '

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

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

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

1
@ घोषी - केवल पढ़ने के लिए कीवर्ड है - मैं इससे सहमत हो सकता हूं। लेकिन ओपी केवल पढ़ने की बात नहीं कर रहा है। उदाहरण के लिए removeकेवल पढ़ा नहीं जाता है। मेरी समझ में ओपी सब कुछ सार्वजनिक करना चाहता है - प्रस्तावित बदलाव से पहले मूल कोड की तरह public Thing[] getThings(){return things;}यह वही है जो मुझे पसंद नहीं है।
वेक्टर

2

आपने पूछा: क्या मुझे हमेशा एक आंतरिक डेटा संरचना को पूरी तरह से अलग करना चाहिए?

संक्षिप्त उत्तर: हां, ज्यादातर समय लेकिन हमेशा नहीं ।

दीर्घ उत्तर: मुझे लगता है कि कक्षाएं निम्नलिखित श्रेणियों में अनुसरण करती हैं:

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

  2. कंटेनर कक्षाएं जो संग्रह को एन्क्रिप्ट करती हैं। एसटीएल में क्लासिक कंटेनर क्लासेस हैं। मैं विचार करता हूं std::stringऔर std::wstringउनमें भी। वे कपोल-कल्पना के साथ सौदा करने के लिए, लेकिन एक अमीर इंटरफेस प्रदान std::vector, std::stringऔर std::wstringभी कच्चे डेटा तक पहुँच प्राप्त करने की क्षमता प्रदान करते हैं। मैं उन्हें खराब तरीके से डिजाइन की गई कक्षाओं को कॉल करने में जल्दबाजी नहीं करूंगा। मैं इन वर्गों के कच्चे डेटा को उजागर करने का औचित्य नहीं जानता। हालाँकि, मेरे पास, मेरे काम में, कच्चे जाल को उजागर करने के लिए आवश्यक था जब प्रदर्शन के कारणों के लिए लाखों मेष नोड्स और उन जाल नोड्स पर डेटा के साथ काम कर रहा था।

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

  3. कक्षाएं जो अधिकतर प्रकृति में कार्यात्मक होती हैं। उदाहरण: std::istream,, std::ostreamSTL कंटेनरों के पुनरावृत्तियों। इन वर्गों के आंतरिक विवरणों को उजागर करना बिल्कुल मूर्खतापूर्ण है।

  4. हाइब्रिड कक्षाएं। ये ऐसी कक्षाएं हैं जो कुछ डेटा संरचना को एन्क्रिप्ट करती हैं, लेकिन एल्गोरिथम कार्यक्षमता भी प्रदान करती हैं। व्यक्तिगत रूप से, मुझे लगता है कि ये खराब विचार डिजाइन का परिणाम हैं। हालांकि, यदि आप उन्हें ढूंढते हैं, तो आपको यह तय करना होगा कि केस के आधार पर किसी मामले पर उनके आंतरिक डेटा को उजागर करना समझ में आता है या नहीं।

निष्कर्ष में: मैंने केवल एक बार एक वर्ग की आंतरिक डेटा संरचना को उजागर करने के लिए आवश्यक पाया है जब यह एक प्रदर्शन अड़चन बन गया है।


मुझे लगता है कि सबसे महत्वपूर्ण कारण यह है कि एसटीएल अपने आंतरिक डेटा को उजागर करता है सभी कार्यों के साथ संगतता है जो संकेत की अपेक्षा करते हैं, जो बहुत सारे हैं।
सियुआन रेन

0

कच्चे डेटा को सीधे वापस करने के बजाय, ऐसा कुछ प्रयास करें

class ClassA {
  private Things[] things;
  ...
  public Things[] asArray() { return things; }
  public List<Thing> asList() { ... }
  ...
}

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

class ClassA {
  private List<Thing> things;
  ...
  public Things[] asArray() { return things.asArray(); }
  public List<Thing> asList() { return things; }
  ...
}

अब आपके पास उचित एनकैप्सुलेशन है, कार्यान्वयन विवरण छिपाएं, और पीछे की संगतता (एक लागत पर) प्रदान करें।


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

1
@ वैक्टर - आप सही हैं। लौटाया गया डेटा स्ट्रक्चर अभी भी म्यूट है और साइड-इफ़ेक्ट्स जानकारी को छुपा कर मार देंगे।
बॉबडालिश

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

@ थोबडालिश: मूल संग्रह की एक प्रति क्यों नहीं लौटाया?
जियोर्जियो

1
@ डबडलगिश: जब तक अच्छे प्रदर्शन के कारण नहीं हैं, मैं आंतरिक डेटा संरचनाओं के संदर्भ को वापस लेने पर विचार करूंगा ताकि इसके उपयोगकर्ताओं को उन्हें बहुत खराब डिजाइन निर्णय के रूप में बदल सकें। किसी वस्तु की आंतरिक स्थिति को केवल उचित सार्वजनिक विधियों के माध्यम से बदला जाना चाहिए।
जियोर्जियो

0

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

class ClassA{

    public ClassA(){
        things = new ArrayList<Thing>();
    }

    private List<Thing> things; // stores data

    // stuff omitted

    public List<Thing> getThings(){
        return things;
    }

}

इस तरह आप बदल सकते हैं ArrayListकरने के लिए LinkedListया कुछ और, और आप सभी जावा संग्रह (सरणियों के बगल में) है कि बाद से किसी भी कोड (छद्म?) रैंडम एक्सेस शायद लागू करेगा तोड़ने नहीं होगा List

आप इसका उपयोग भी कर सकते हैं Collection, जो कम तरीकों की पेशकश करते हैं, Listलेकिन रैंडम एक्सेस के बिना संग्रह का समर्थन कर सकते हैं, या Iterableजो धाराओं का समर्थन भी कर सकते हैं , लेकिन एक्सेस विधियों की अवधि में बहुत अधिक पेशकश नहीं करते हैं ...


-1 - खराब समझौता और विशेष रूप से सुरक्षित आईएमओ नहीं: आप ग्राहक को आंतरिक डेटा संरचना को उजागर कर रहे हैं, बस इसे मास्क कर रहे हैं और सर्वश्रेष्ठ की उम्मीद कर रहे हैं क्योंकि "जावा संग्रह ... शायद सूची को लागू करेगा ।" यदि आपका समाधान वास्तव में बहुरूपिक / विरासत आधारित था - जो कि सभी संग्रह हमेशा Listव्युत्पन्न वर्गों के रूप में लागू होते हैं, तो यह अधिक समझ में आता है, लेकिन सिर्फ "सर्वश्रेष्ठ की उम्मीद करना" एक अच्छा विचार नहीं है। "एक अच्छा प्रोग्रामर एक ही रास्ते पर दोनों तरह से दिखता है"।
वेक्टर

@ वैक्टर हां, मैं मान रहा हूं कि भविष्य के जावा संग्रह लागू होंगे List(या Collection, या कम से कम Iterable)। यह इन इंटरफेसों का पूरा बिंदु है, और यह शर्म की बात है कि जावा एरेज़ उन्हें लागू नहीं करता है, लेकिन वे जावा में संग्रह के लिए आधिकारिक इंटरफ़ेस हैं, इसलिए ऐसा नहीं है कि किसी भी जावा संग्रह को ग्रहण करने के लिए उन्हें लाया जाता है - जब तक कि संग्रह पुराना न हो से List, और उस मामले में इसे AbstractList के साथ लपेटना बहुत आसान है ।
इदं आर्य

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

1
@Vector हाँ, उन डाल सकता Listमें ArrayListहै, लेकिन यह कार्यान्वयन की तरह 100% संरक्षित किया जा सकता है नहीं है - आपको हमेशा पहुंच निजी क्षेत्रों के लिए प्रतिबिंब का उपयोग कर सकते हैं। ऐसा करने पर उसे फेंक दिया जाता है, लेकिन कास्टिंग भी उस पर की जाती है (हालांकि ज्यादा नहीं)। एनकैप्सुलेशन का मुद्दा दुर्भावनापूर्ण हैकिंग को रोकना नहीं है - बल्कि, यह उपयोगकर्ताओं को उन कार्यान्वयन विवरणों के आधार पर रोकना है जिन्हें आप बदलना चाहते हैं। Listइंटरफ़ेस का उपयोग ठीक यही करता है - वर्ग के उपयोगकर्ता Listकंक्रीट ArrayListक्लास के बजाय इंटरफ़ेस पर निर्भर कर सकते हैं जो बदल सकते हैं।
इदं आर्य

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

-2

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


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