2012-05-02 16 views
65

संभव डुप्लिकेट:
Why use getters and setters?गेटर्स और सेटर्स का क्या मतलब है?

मैं Java पर किताबें पढ़ लिया है, कह रही है कि यह इस तरह x और y के रूप में चर के लिए setters और getters बनाने के लिए अच्छा है। उदाहरण के लिए:

public int getX(){ 
    return x; 
} 

public void setX(int x){ 
    this.x = x; 
} 

लेकिन उस से अंतर और

...(shape.x)... // basically getX() 

और

shape.x = 90; // basically setX() 

setters और getters बेहतर हैं, तो आप क्या व्यावहारिक समस्याओं पैदा होता मुझे समझा सकता है क्या है ?

+2

यह http://stackoverflow.com/a/1568230/985143 –

+1

सटीक डुप्लिकेट @ZazGmy –

+4

सच यह है कि [जीएस] ईटर एक बड़ा बोझ हैं और आपको वास्तव में प्रत्येक मामले में लागत बनाम लाभ का वजन करना चाहिए। ऐसे उदाहरण हैं जहां सार्वजनिक क्षेत्र (विशेष रूप से यदि आप उन्हें अंतिम बना सकते हैं!) सही तरीके हैं। –

उत्तर

71

के कई कारण:

  • आप क्षेत्र का उपयोग

    shape.x = 90

तो जैसे आप भविष्य में किसी भी तर्क नहीं जोड़ सकते डेटा मान्य करने के लिए अनुमति देते हैं ।

कहते हैं कि तुम यह नहीं कर सकता है, लेकिन अगर आप

public void setShapeValue(int shapeValue){ 
    if(shapeValue < 100){ 
    //do something here like throw exception. 
    } 
} 
  • आप लिखने तर्क पर नकल की तरह कुछ नहीं जोड़ सकते हैं जैसे setters था x 100 से कम नहीं हो सकता है (CopyOnWriteArrayList देखें)
  • एक अन्य कारण आपकी कक्षा के बाहर के क्षेत्रों तक पहुंचने के लिए आपको उन्हें सार्वजनिक, संरक्षित या डिफ़ॉल्ट चिह्नित करना होगा, और इस प्रकार आप नियंत्रण खो देंगे। जब डेटा Encapsulation तोड़ने और सामान्य OOPS पद्धति को तोड़ने के लिए डेटा बहुत अधिक आंतरिक होता है।

हालांकि के लिए स्थिरांक

तरह
public final String SOMETHING = "SOMETHING"; 

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

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

हालांकि ऐसे मामलों में आपको यह सुनिश्चित करने के लिए गेटटर विधि में सावधान रहना होगा कि आप वस्तुओं का संदर्भ न दें (यदि आपकी कक्षा में उदाहरण के रूप में वस्तु है)।

हम गेटर्स और सेटर्स का उपयोग करके किसी भी पैकेज में निजी चर का उपयोग कर सकते हैं।

+0

"लिखने पर प्रतिलिपि" वैसे भी 99% बार समझ में नहीं आता है। कल्पना करें कि 'shape.x' पर "लिखने पर प्रतिलिपि बनाएं' ... – Pacerier

+1

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

+0

झूठा। आप मुख्य कोड में एक कथन के साथ डेटा मान्य कर सकते हैं, या एक वैध समारोह। – DarmaniLink

7

गेटर और सेटर फ़ंक्शंस का उपयोग बाधाओं और encapsulation के लिए अनुमति देते हैं। चलो कहते हैं एक्स त्रिज्या है। shape.x = -10 ज्यादा समझ नहीं लेगा। साथ ही, अगर कोई अवैध मान सेट करने का प्रयास करता है, तो आप एक त्रुटि प्रिंट कर सकते हैं, डिफ़ॉल्ट मान सेट कर सकते हैं, या कुछ नहीं कर सकते हैं।

सदस्य चर को निजी बनाने के लिए यह अच्छा अभ्यास है ताकि उन्हें सीधे प्रोग्रामों द्वारा संशोधित नहीं किया जा सके।

Mutator functions
Encapsulation

1

कारणों में से बहुत सारे हैं। यहां महज कुछ हैं।

  1. एक्सेसर्स, विशेष रूप से गेटर्स, अक्सर इंटरफेस में दिखाई देते हैं। आप एक इंटरफ़ेस में सदस्य चर निर्धारित नहीं कर सकते हैं।
  2. एक बार जब आप इस सदस्य चर का पर्दाफाश कर लेते हैं, तो आप इसे लागू करने के तरीके के बारे में अपना मन नहीं बदल सकते हैं। उदाहरण के लिए, यदि आपको समेकन जैसे पैटर्न पर स्विच करने के लिए बाद में आवश्यकता दिखाई देती है, जहां आप "x" प्रॉपर्टी को वास्तव में कुछ नेस्टेड ऑब्जेक्ट से आना चाहते हैं, तो आप उस मान को कॉपी करने और इसे सिंक में रखने की कोशिश करते हैं। अच्छा नही।
  3. अधिकांश समय आप सेटर को उजागर करने से अधिक बेहतर होते हैं। आप एक्स जैसे सार्वजनिक क्षेत्रों के साथ ऐसा नहीं कर सकते हैं।
0

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

+0

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

0

यह ओओपी के encapsulation सिद्धांत को लागू करके किया जाता है।

किसी ऑब्जेक्ट के घटकों तक पहुंच प्रतिबंधित करने के लिए एक भाषा तंत्र।

इसका मतलब है, आपको अपने वर्गों के गुणों और विधियों के लिए दृश्यता को परिभाषित करना होगा। 3 आम दृश्यताएं हैं:

  • निजी: केवल वर्ग विशेषताएँ/विधियों को देख और उपयोग कर सकता है।
  • संरक्षित: केवल वर्ग और उसके बच्चे विशेषताएँ/विधियों को देख और उपयोग कर सकते हैं।
  • सार्वजनिक: प्रत्येक वर्ग विशेषताएँ/विधियों को देख और उपयोग कर सकता है।

जब आप निजी/संरक्षित विशेषताओं की घोषणा करते हैं, तो आपको मूल्य (प्राप्त) प्राप्त करने और मूल्य (सेट) को बदलने के तरीकों को बनाने के लिए प्रोत्साहित किया जाता है। दृश्यता के बारे में एक उदाहरण [ArrayList][2] वर्ग है: इसमें size संपत्ति है जो आंतरिक सरणी के वास्तविक आकार को जानने के लिए है।केवल वर्ग चाहिए, अपने मूल्य को बदलने तो कोड की तरह

public class ArrayList<E> { 
    private int size; 
    private Object[] array; 
    public getSize() { 
     return this.size; 
    } 
    public void add(E element) { 
     //logic to add the element in the array... 
     this.size++; 
    } 
} 

इस उदाहरण में कुछ है, तो आप देख सकते हैं कि आकार मूल्य केवल वर्ग के तरीकों के अंदर बदल सकते हैं, और आप इसका वास्तविक आकार प्राप्त कर सकते हैं इसे अपने कोड में बुला (यह परिवर्तनशील नहीं):

public void someMethod() { 
    List<String> ls = new ArrayList<String>(); 
    //adding values 
    ls.add("Hello"); 
    ls.add("World"); 
    for(int i = 0; i < ls.size(); i++) { 
     System.out.println(ls.get(i)); 
    } 
} 
0

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

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

1

उत्तर देने से पहले, हमें पहले कुछ पता होना चाहिए ...! "जावाबीन"।
जावाबीन जावा कक्षाएं हैं जिनमें गुण हैं। हमारे उद्देश्य के लिए, निजी उदाहरण चर के रूप में गुणों के बारे में सोचें। चूंकि वे निजी हैं, इसलिए उनकी कक्षा के बाहर से तक पहुंचने का एकमात्र तरीका कक्षा में 'विधियों' के माध्यम से किया जा सकता है।
गुणों के मूल्य को बदलने वाले विधियों को सेटर विधियों कहा जाता है, और संपत्ति के मूल्य को पुनर्प्राप्त करने वाले विधियों को गेटर विधियों कहा जाता है।

0

क्योंकि हम ऑब्जेक्ट उन्मुख प्रोग्रामिंग भाषा का उपयोग कर रहे हैं। यहां हम डेटा छिपाने और encapsulation का उपयोग कर रहे हैं। चर चाहिए सीधा नहीं पहुंचा बाहर की ओर दुनिया से (डेटा छुपा achiving के लिए), ताकि हम उसे निजी इसलिए

shape.x

सही नहीं है पैदा करेगा। गेटटर और सेटर विधि का उपयोग x के मान को प्राप्त करने और सेट करने के लिए किया जाता है जो एन्कैप्यूलेशन को प्राप्त करने का तरीका है।

4

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

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

3

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

यदि आपने एक्सेसर फ़ंक्शंस का उपयोग करने के लिए उपेक्षित किया है और अपने क्लाइंट कोड को सीधे YourClass.x तक पहुंचने दें, तो आपको अब अपने क्लाइंट कोड को फिर से लिखना होगा जो कभी भी YourClass.x को छुआ है। लेकिन अगर आप शुरुआत से YourClass.getX() और YourClass.setX() का उपयोग कर रहे थे, तो आपको केवल अपने क्लास को फिर से लिखना होगा।

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

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

4

उपयोगकर्ता गेटर और सेटर के लिए एक और अच्छा कारण निम्न उदाहरण

public class TestGetterSetter{ 
    private String name ; 


    public void setName(String name){ 
     this.name = name ; 
    } 


    public String getName(String name){ 
     return this.name ; 
    } 
} 

getters और setters की बात यह है कि केवल वे निजी varialble उपयोग करने के लिए इस्तेमाल किया जा के लिए होती हैं है द्वारा समझ में किया जा सकता है, जो वे कर रहे हैं हो रही है या सेटिंग। इस तरह आप encapsulation प्रदान करते हैं और बाद में आपके कोड को दोबारा संशोधित या संशोधित करना अधिक आसान होगा।

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

public class TestGetterSetter{ 
    private String name ; 


    public void setName(String name){ 
     this.name = name ; 
    } 


    public String getName(String name){ 
     if (this.name == null){ 
      setName("Guest"); 
     } 
     return this.name ; 
    } 
} 

गेटर्स और सेटर के साथ पाने और सेट के साथ शुरू करने की कोई आवश्यकता नहीं है - वे केवल सामान्य सदस्य कार्य हैं। हालांकि यह ऐसा करने के लिए एक सम्मेलन है। (खासकर यदि आप जावा बीन्स का उपयोग करें)

+5

गेटर्स और सेटर रीफैक्टरिंग के लिए सबसे खराब एनाथेमा हैं! उदाहरण के लिए, स्ट्रिंग से डेट फ़ील्ड में अपनी 50-संपत्ति जावाबीन में से 30 को बदलने का प्रयास करें। –

3

मूल रूप से, गेटर/सेटर पैटर्न उसके बाहरी interface से एक class के आंतरिक encapsulating से अच्छा वस्तु उन्मुख डिजाइन को बढ़ावा देने के लिए बनाया गया था।

  • संपत्ति

इससे आपके प्रश्न का का सबसे अच्छा जवाब Why use getters and setters?

6

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

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

एक जटिल संख्या वास्तविक और काल्पनिक भागों के साथ प्रपत्र a + bi पर लिखा जा सकता है, जो अपने आप [gs]etRealPart और [gs]etImaginaryPart को अच्छी तरह से उधार।

हालांकि, कुछ मामलों में ध्रुवीय रूप re^(iθ) पर जटिल संख्याओं के बारे में तर्क करना आसान है, [gs]etRadius (आर) और [gs]etAngle (θ) दे रहा है।

आप [gs]etComplexNumber(realPart, imaginaryPart) और [gs]etComplexNumber(radius, angle) जैसी विधियों का भी खुलासा कर सकते हैं। तर्क प्रकारों के आधार पर इन्हें अलग-अलग नामों की आवश्यकता हो सकती है या नहीं, लेकिन फिर कक्षा 'उपभोक्ता अपनी आवश्यकताओं के अनुरूप उपयोग कर सकते हैं।

दो रूपों में अंतर-परिवर्तनीय हैं; आप एक से दूसरे में काफी आसानी से परिवर्तित कर सकते हैं, इसलिए कक्षा के आंतरिक भंडारण के लिए कक्षा का उपयोग किस वर्ग के उपभोक्ताओं के लिए अप्रासंगिक है। हालांकि, उपभोक्ता किसी भी रूप का उपयोग कर सकते हैं। यदि आप आंतरिक प्रतिनिधित्व के लिए फॉर्म + द्वि का चयन करते हैं, और का खुलासा करते हैं कि गेटर्स और सेटर्स के बजाय फ़ील्ड्स का उपयोग करके, न केवल क्लास उपभोक्ताओं को उस फॉर्म का उपयोग करने के लिए मजबूर करते हैं, तो आप बाद में आसानी से अपना मन बदल सकते हैं और आंतरिक को प्रतिस्थापित नहीं कर सकते re^(iθ) के साथ प्रतिनिधित्व क्योंकि यह आपके विशेष परिदृश्य में लागू करना आसान हो जाता है। आप जिस सार्वजनिक एपीआई को परिभाषित कर चुके हैं, उसके साथ अटक गए हैं, जो अनिवार्य है कि विशेष रूप से असली और काल्पनिक भागों को विशिष्ट फ़ील्ड नामों का उपयोग करके उजागर किया जाता है।

+0

यह माप की इकाइयों, या पूर्ण बनाम रिश्तेदार निर्देशांक जैसी चीजों पर भी लागू होता है। –

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