क्या एक वर्ग के तरीकों को अपने स्वयं के गेटर्स को कॉल करना चाहिए और बसना चाहिए?


53

जहां मैं काम करता हूं मैं बहुत सारी कक्षाएं देखता हूं जो इस तरह की चीजें करती हैं:

public class ClassThatCallsItsOwnGettersAndSetters {

    private String field;

    public String getField() {
        return field;
    }

    public void setField(String field) {
        this.field = field;
    }

    public void methodWithLogic() {
        setField("value");
        //do stuff
        String localField = getField();
        //do stuff with "localField"
    }
}

अगर मैंने इसे खरोंच से लिखा है, तो मैंने methodWithLogic()इसके बजाय इस तरह लिखा होगा :

public class ClassThatUsesItsOwnFields {

    private String field;

    public String getField() {
        return field;
    }

    public void setField(String field) {
        this.field = field;
    }

    public void methodWithLogic() {
        field = "value";
        //do stuff            
        //do stuff with "field"
    }
}

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

क्या पहली विधि के लाभ हैं? क्या पहला तरीका वास्तव में बेहतर है?


जब मैं कुछ अपरिचित कोड डिबग कर रहा हूं, तो यह कहने के लिए कि बग उस विधि में कुछ साइड इफेक्ट नहीं है? आपकी इकाई परीक्षण :)
जोशुआ टेलर

1
अपने आंतरिक कोड में गेटर्स / सेटर का उपयोग करने से आप अपने कोड में एक ब्रेकपॉइंट बना सकते हैं यदि आप इसे डीबगर के माध्यम से जा रहे हैं। यह आपको यह सुनिश्चित करने की भी अनुमति देता है कि यदि सेटिंग सेट करने / मूल्य प्राप्त करने में कुछ भी गलत हो रहा है, तो आप जानते हैं कि यह उस पद्धति के कारण है और कुछ अमान्य पहुंच के कारण नहीं। कुल मिलाकर, यह अधिक निरंतरता कोड प्रदान करता है।
calalater 16

जवाबों:


46

मैं यह नहीं कहूंगा कि कौन बेहतर या बदतर है, क्योंकि यह आंशिक रूप से आपकी स्थिति पर निर्भर करता है (मेरी राय में)। लेकिन विचार करें कि आपके गेटर्स और सेटर बाद में कार्यान्वयन को बदल सकते हैं, और उन्हें दरकिनार करके उस तर्क को छोड़ देंगे।

उदाहरण के लिए, यदि आप बाद में कुछ सेटर फील्ड्स में "गंदे" झंडे को जोड़ते हैं, तो क्या होता है? अपने आंतरिक कोड में अपने वासियों को बुलाकर आप किसी अन्य कोड को बदले बिना गंदा झंडा सेट करेंगे। कई स्थितियों में यह एक अच्छी बात होगी।


लेकिन जब आप बैकएंड में डेटा को इनिशियलाइज़ कर रहे होते हैं तो आप क्या चाहते हैं कि आप इसे गंदा न समझें। यदि आप setField()शुरू से ही फोन करते हैं तो आपने बग को पेश किया है।
डेनियल कपलान

6
ठीक है, इसलिए मैं कहता हूं कि यह स्थिति पर आंशिक रूप से निर्भर करता है। हो सकता है कि आपका डेटा इनिशियलाइज़ेशन सेटर्स को छोड़ दे, लेकिन दूसरे लॉजिकल कोड को नहीं करना चाहिए। ऐसे नियम चुनें जो उपयुक्त हों और इसके साथ रहें।
मैट एस

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

33

सेटर को सीधे कॉल करना, अपने आप में, एक समस्या नहीं है। सवाल वास्तव में होना चाहिए: हमारा कोड हर जगह क्यों बसता है?

म्यूटेबल क्लासेज एक खतरनाक गेम है, खासकर जहां क्लास खुद अपने राज्य का प्रबंधन करती है। गौर कीजिए कि उनमें से कितने वास्‍तव में मौजूद हैं। कितने को कंस्ट्रक्टर में सेट किया जा सकता है और फिर पूरी तरह से वर्ग से ही अलग हो सकता है?

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

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


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

@DanielKaplan: मैं बिल्कुल यही कह रहा हूं। :) मैं इस एक के साथ जवाब और टिप्पणी के बीच फटा हुआ था, लेकिन मैं वास्तव में महसूस नहीं करता कि एक सही जवाब है जो बड़ा सवाल नहीं पूछता है।
पीडीआर

9

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


1
मैं आपके पहले वाक्य और आपके बाकी पैराग्राफ के बीच के संबंध को नहीं देखता। पहला वाक्य कहता है कि एक वर्ग को अपने स्वयं के गेटर्स को कॉल करना चाहिए और बसना चाहिए। बाकी पैराग्राफ बताते हैं कि क्‍लाइंट कोड (यानी: क्‍लास का उपयोग करने वाला कोड) को सीधे खेतों तक पहुंचने के बजाय गेटर्स और सेटर का उपयोग करना चाहिए। लेकिन मैं यह नहीं देखता कि किस कारण से वर्ग को सीधे अपने खेतों तक नहीं जाना चाहिए ।
डैनियल कपलान

1
@DanielKaplan मेरा कहना है कि कारण एक और एक ही हैं। कि अगर आप बाद में सेटर लॉजिक जोड़ते हैं, तो यह आंतरिक कोड को बाहरी की तरह ही (संभावित रूप से) प्रभावित करता है।
माइकल

2
@ मिचेल: अक्सर किसी वर्ग के अपने स्वयं के गेटर्स / सेटर का उपयोग न करने के अच्छे कारण हो सकते हैं। एक सामान्य परिदृश्य वह है जहां फ़ॉर्म के कई सेटर हैं। someField=newValue; refresh(); यदि विधि कई फ़ील्ड्स को सेट करने की अनुमति देती है, तो कॉल करने वालों को कॉल करने के लिए उन फ़ील्ड्स को लिखना निरर्थक "ताज़ा" संचालन का कारण होगा। सभी क्षेत्रों को लिखना और फिर refresh()एक बार कॉल करना अधिक कुशल और सहज दिखने वाला ऑपरेशन हो सकता है।
सुपरकैट

6

एक शब्द में अपने सवालों के जवाब देने के लिए, हाँ।

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

कहो तुम कुछ इस तरह है:

public class Vehicle
{
    private int year;
    private String make;

    public Vehicle(int year, String make)
    {
        setYear(year);
        setMake(make);
    }

    public void setYear(int year)
    {
        this.year = year;
    }

    public void setMake(String make)
    {
        this.make = make;
    }
}

वर्ष के लिए बसने वालों को बुलाना और वर्तमान में कोई कार्यक्षमता नहीं जोड़ सकता है, लेकिन क्या होगा यदि आप बसने वालों को इनपुट सत्यापन जैसे कुछ जोड़ना चाहते हैं?

public class Vehicle
{
    private int year;
    private String make;

    public Vehicle(int year, String make)
    {
        setYear(year);
        setMake(make);
    }

    public void setYear(int year)
    {
        if(year > 0)
        {
            this.year = year;
        }
        else
        {
            System.out.println(year + " is not a valid year!");
        }
    }

    public void setMake(String make)
    {
        this.make = make;
    }
}

5

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


3

यदि आप सार्वजनिक इंटरफ़ेस द्वारा प्रदान की गई किसी चीज़ को पूरा करने की कोशिश कर रहे हैं, तो गेटर्स / सेटर्स का उपयोग करें।

हालाँकि, वर्ग के स्वामी / डेवलपर के रूप में, आपको अपने कोड के निजी वर्गों (पाठ्यक्रम की कक्षा के भीतर से) तक पहुंचने की अनुमति है, लेकिन आप खतरों को कम करने के लिए भी जिम्मेदार हैं।

तो हो सकता है कि आपके पास कुछ आंतरिक सूची पर पुनरावृत्ति करने वाला एक गेटर हो, और आप पुनरावृति प्राप्त किए बिना वर्तमान मान प्राप्त करना चाहते हैं। इस स्थिति में, निजी चर का उपयोग करें।

public class MyClass
{
    private int i;
    private List<string> list;
    public string getNextString()
    {
        i++;
        return list[i];
    }

    private void getString()
    {
        // Do not increment
        string currentString = list[i];

        // Increment
        string nextString = getNextString();
    }
}

क्या आप इसके लिए तर्क दे सकते हैं?
डैनियल कापलान

1

हाँ। गेटर्स और सेटर राज्य का प्रतिनिधित्व करते हैं, इसलिए इस सवाल को घुमाएं - क्या आप वस्तुओं के राज्य को बदलने के कई तरीकों पर उसी तरह से नज़र रखना चाहते हैं जब तक आपको नहीं करना है?

कम चीजें आपको बेहतर का ध्यान रखना होगा - यही कारण है कि अपरिवर्तनीय वस्तुओं से निपटना आसान है।

गौर कीजिए, सार्वजनिक क्षेत्र और सार्वजनिक गेटटर / सेटर दोनों होने से आपको रोकने के लिए कुछ भी नहीं है - लेकिन आप क्या हासिल करेंगे?

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


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

@DanielKaplan: मैं समझता हूं कि, और मैं जो कह रहा हूं, वह यह है कि जहां तक ​​व्यावहारिक है आपको उनके साथ ऐसा ही व्यवहार करना चाहिए।
जमरनो

@DanielKaplan: आपके पास एक निजी सेटर और एक सार्वजनिक सेटर हो सकता है, जिसका कम से कम एक ही परिणाम (सभी साइड इफेक्ट समान) कम से कम एमोमेंट के लिए हो सकता है, लेकिन जो चीज़ आपको डायजेस्ट करने की क्षमता के अलावा अन्य लाभ देगी? इस परिदृश्य और आप जो वर्णन करते हैं, उसके बीच का अंतर यह है कि आप गेटर्स / सेटर के बाहर राज्य तक पहुंचने में सक्षम होने से बच नहीं सकते हैं , लेकिन आप वास्तव में ऐसा करने से बच सकते हैं। जब तक आपको अपने कोड को जटिल नहीं करना है।
जमरनो

1

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

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


1

मैं कहूंगा नहीं ..

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

JVM गेटअवे / सेटर्स को बार-बार कॉल इनलाइन करेगा। तो, यह कभी नहीं एक प्रदर्शन मुद्दा है। चर का उपयोग करने का लाभ पठनीयता और IMHO है, मैं इसके लिए जाऊंगा।

उम्मीद है की यह मदद करेगा..

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