जावा `अंतिम` विधि: यह क्या वादा करता है?


141

एक जावा वर्ग में एक विधि को परिभाषित किया जा सकता है final, यह चिह्नित करने के लिए कि इस विधि को ओवरराइड नहीं किया जा सकता है:

public class Thingy {
    public Thingy() { ... }
    public int operationA() {...}
    /** this method does @return That and is final. */
    public final int getThat() { ...}
}

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

मेरा प्रश्न यह है: एक OOP के दृष्टिकोण से, मैं समझ गया था कि, एक विधि finalको परिभाषित करके , क्लास डिजाइनर वादा करता है कि यह विधि हमेशा वर्णित के रूप में काम करेगी, या निहित होगी। लेकिन अक्सर यह वर्ग लेखक के प्रभाव के बाहर हो सकता है, अगर विधि क्या कर रही है और अधिक जटिल है तो बस एक संपत्ति वितरित करना ।

सिंटैक्टिक बाधा मेरे लिए स्पष्ट है, लेकिन ओओपी अर्थ में निहितार्थ क्या है? क्या finalइस अर्थ में सही ढंग से अधिकांश वर्ग लेखकों द्वारा उपयोग किया जाता है?

किस तरह का "अनुबंध" एक finalविधि का वादा करता है?

जवाबों:


155

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

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

कुछ को अनुकूलन योग्य होने से रोकने के कई कारण हैं, जिनमें शामिल हैं:

  • प्रदर्शन - कुछ संकलक विश्लेषण कर सकते हैं और ऑपरेशन का अनुकूलन कर सकते हैं, विशेष रूप से साइड-इफेक्ट के बिना।

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

  • विश्वसनीयता और अनुबंध - वस्तुओं पुरातन (से बने हुए हैं int, char, double, आदि) और / या अन्य वस्तुओं। उन घटकों पर लागू सभी ऑपरेशन लागू नहीं होने चाहिए या बड़े ऑब्जेक्ट में उपयोग किए जाने पर भी तर्कसंगत नहीं होने चाहिए। finalयह सुनिश्चित करने के लिए संशोधक के तरीकों का उपयोग किया जा सकता है। काउंटर क्लास इसका एक अच्छा उदाहरण है।


public class Counter {
    private int counter = 0;

    public final int count() {
        return counter++;
    }

    public final int reset() {
        return (counter = 0);
    }
}

यदि public final int count()विधि नहीं है final, तो हम ऐसा कुछ कर सकते हैं:

Counter c = new Counter() {   
    public int count() {
        super.count();   
        return super.count();   
    } 
}

c.count(); // now count 2

या इस तरह का कुछ:

Counter c = new Counter() {
    public int count() {
        int lastCount = 0;
        for (int i = super.count(); --i >= 0; ) {
            lastCount = super.count();
        }

        return lastCount;
    }
}

c.count(); // Now double count

27

"अनुबंध" किस तरह का एक अंतिम तरीका वादा करता है?

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


लेकिन क्या यह नज़रिया मेरे मूल प्रश्न का अर्थ नहीं है "यह अंतिम पद्धति हमेशा वादे के अनुसार व्यवहार करेगी" कि मुझे किसी अंतिम विधि के अंदर से किसी गैर-अंतिम तरीके को नहीं कहना चाहिए? क्योंकि, अगर मैं कहा जाता है कि विधि समाप्त हो गई है और इसलिए मैं अपने अंतिम तरीके के व्यवहार की गारंटी नहीं दे सकता हूं?
टावी

8

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

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

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

class A implements Runnable {
  final String caption = "Some caption";                           

  void run() {
    // no need to synchronize here to see proper value of final field..
    System.out.println(caption);
  }
}  

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

@ आप सही हैं कि finalयौगिक वस्तुओं में किए गए परिवर्तनों की दृश्यता सुनिश्चित नहीं करेंगे, जैसे कि Map
विक्टर सोरोकिन

0

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


1
हां, मेरा मतलब यही था। सही। मुझे "कमजोर गारंटी" शब्द पसंद है :-) और मैं (ज्यादातर) सी ++ की तरह const। के रूप में char const * const = "Hello"या char const * const addName(char const * const name) const...
टॉवी

0

नहीं, यह वर्ग लेखक के प्रभाव से बाहर नहीं है। आप इसे अपने व्युत्पन्न वर्ग में ओवरराइड नहीं कर सकते हैं, इसलिए यह वही करेगा जो बेस क्लास लेखक का इरादा है।

http://download.oracle.com/javase/tutorial/java/IandI/final.html

वर्थ नोटिंग वह हिस्सा है जहां यह सुझाव देता है कि निर्माणकर्ताओं से बुलाए गए तरीके होने चाहिए final


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