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

public class TestClass {
    public int doSomething(Message message) {
        int resultCode;
        
        resultCode = checkFirstThing(message) //Returns 0 if succeed or 1 if not
        //Exit if resultCode != 0
        
        //do something with message

        Permission perm = message.author.perm

        resultCode = checkSecondThing(perm) //Returns 0 if succeed or 2 if not
        //Exit if resultCode != 0

        //Excecute something

        resultCode = checkThirdThing() //Returns 0 if succeed or 3 if not
        //Exit if resultCode != 0

        //do Something if resultCode still 0
        return resultCode
    }
}

मेरी समस्या यह है कि मैं प्रत्येक चेक-फ़ंक्शन के बाद if(resultCode != 0) return resultCode नहीं जोड़ना चाहता, क्योंकि यह डुप्लिकेट कोड होगा।

आपकी मदद के लिए टैंक :)

0
DragonCoder 10 मई 2021, 10:08

2 जवाब

सबसे बढ़िया उत्तर

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

चलो साथ - साथ शुरू करते हैं

public class Result {

    private int code;

    public Result(int code) {
        this.code = code;
    }

    public int getCode() {
        return code;
    }

    public boolean isSuccess() {
        return 0 == code;
    }

}

तदनुसार, आप एक आदिम int के बजाय Result का एक उदाहरण वापस करने के लिए अपनी अन्य विधियों को फिर से लगाते हैं।

public Result checkFirstThing(/* parameters */) {
    // implementation
}

public Result checkSecondThing(/* parameters */) {
    // implementation
}

...

इस बिंदु पर हमने बहुत कुछ हासिल नहीं किया है, doSomething विधि लगभग एक जैसी दिखेगी। हालांकि, Result वर्ग के लिए निम्न विधि देखें

public Result and(Supplier<? extends Result> code) {
    return isSuccess() ? code.get() : this;
}

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

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

अब आप बिना किसी if स्टेटमेंट को जोड़े अपनी मेथड कॉल्स को एक साथ चेन करने के लिए इस मेथड का इस्तेमाल कर सकते हैं।

public int doSomething(Message message) {
    Result result = checkFirstThing(/* parameters */)
         .and(() -> checkSecondThing(/* parameters */))
         .and(() -> checkThirdThing(/* parameters */));
    if (result.isSuccess()) {
        /* 
         * Do your actual processing. You could also add your main processing 
         * to the method chain above, but I think like this it is more clear
         * for future reading.
         */
    }
    return result.getCode();
}

बीच में बयानों को संबोधित करना

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

Message message = null;
// iniialize message
Result result = checkFirstThing(message).and(() -> {
    Permission perm = message.author.perm;
    return checkSecondThing(perm).and(() -> checkThirdThing(perm));
});

यदि इसे केवल Permission perm = message.author.perm को संबंधित check... विधियों में कॉपी करने की तुलना में बहुत कम पठनीय लगता है।

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

हालाँकि, इस बिंदु पर कुछ redability वापस पाने के लिए, आप विधि श्रृंखला के आंतरिक भाग को एक नई विधि में निकाल सकते हैं

private Result checkAuthorPermissions(Message message) {
    Permission perm = message.author.perm;
    return checkSecondThing(perm).and(() -> checkThirdThing(perm));
}

और बस करो

Result result = checkFirstThing(message)
     .and(() -> checkAuthorPermissions(message));
2
Izruo 10 मई 2021, 11:49

ये कोशिश करें।

class SomethingException extends Exception {
    public final int resultCode;
    SomethingException(int resultCode) {
        this.resultCode = resultCode;
    }
}

void checkResultCode(int resultCode) throws SomethingException {
    if (resultCode != 0)
        throw new SomethingException(resultCode);
}

public int doSomething(Message message) {
    try {
        checkResultCode(checkFirstThing(message));
        //Exit if resultCode != 0            
        //do something with message          
        Permission perm = message.author.perm;
        checkResultCode(checkSecondThing(perm));
        //Exit if resultCode != 0
        //Excecute something
        checkResultCode(checkThirdThing());
        //Exit if resultCode != 0
        //do Something if resultCode still 0
        return 0;
    } catch (SomethingException e) {
        return e.resultCode;
    }
}
1
saka1029 10 मई 2021, 10:47