जावा में डिफ़ॉल्ट कीवर्ड का उद्देश्य क्या है?


94

जावा में एक इंटरफ़ेस एक वर्ग के समान है, लेकिन एक इंटरफ़ेस के शरीर में केवल सार विधियां और finalक्षेत्र (स्थिरांक) शामिल हो सकते हैं ।

हाल ही में, मैंने एक प्रश्न देखा, जो इस तरह दिखता है

interface AnInterface {
    public default void myMethod() {
        System.out.println("D");
    }
}

इंटरफ़ेस परिभाषा के अनुसार, केवल अमूर्त विधियों की अनुमति है। यह मुझे उपरोक्त कोड संकलित करने की अनुमति क्यों देता है? defaultकीवर्ड क्या है ?

दूसरी तरफ, जब मैं नीचे दिए गए कोड को लिखने की कोशिश कर रहा था, तो यह कहता है modifier default not allowed here

default class MyClass{

}

के बजाय

class MyClass {

}

क्या कोई मुझे defaultकीवर्ड का उद्देश्य बता सकता है ? क्या यह केवल एक इंटरफ़ेस के अंदर की अनुमति है? यह किस प्रकार से अलग हो सकता है default(कोई एक्सेस संशोधक नहीं)?


4
जावा 8 में इंटरफेस में डिफ़ॉल्ट तरीके जोड़े गए थे। यह एक पहुँच संशोधक नहीं है, यह एक डिफ़ॉल्ट कार्यान्वयन है।
एरन

2
@ आपको नहीं लगता, इंटरफ़ेस परिभाषा का उल्लंघन करते हुए डिफ़ॉल्ट विधि की शुरूआत? : s
रवि

2
इसने इंटरफ़ेस परिभाषा को बदल दिया। वह परिभाषा अब पुरानी हो चुकी है।
लुई वासरमैन

2
उन्हें लंबोदर का समर्थन करने के लिए पेश किया गया था। प्रोजेक्ट लाम्दा के लिए स्ट्रॉ मैन प्रस्ताव में इनकी आवश्यकता क्यों है, इसका विवरण है।
स्प्रिंटर

जवाबों:


74

यह जावा 8 में एक नई सुविधा है जो ए interfaceलागू करने की अनुमति देता है। जावा 8 JLS-13.5.6 में वर्णित है इंटरफ़ेस विधि घोषणाएँ जो पढ़ती हैं (भाग में)

एक जोड़ा जा रहा है defaultविधि, या एक विधि को बदलने से abstractकरने के लिए default, पहले से मौजूद binaries के साथ संगतता को तोड़ने नहीं है, लेकिन एक कारण हो सकता है IncompatibleClassChangeErrorअगर एक पूर्व मौजूदा बाइनरी प्रयास विधि आह्वान करने के लिए। यह त्रुटि आती है, तो योग्यता प्रकार, Tदो इंटरफेस के एक उप-प्रकार है, Iऔर J, जहां दोनों Iऔर Jएक की घोषणा defaultएक ही हस्ताक्षर और परिणाम के साथ विधि, और न तो Iहै और न ही Jअन्य की एक subinterface है।

JDK 8 में नया क्या है (भाग में)

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


16
ऐसा लगता है, अब इंटरफ़ेस और अमूर्त वर्ग लगभग समान हैं। :)
रवि

16
@jWeaver इंटरफेस में अभी भी कंस्ट्रक्टर, फ़ील्ड्स, निजी तरीके या समान / हैशकोड / स्ट्रॉन्ग के कार्यान्वयन नहीं हो सकते हैं।
लुई वासरमैन

10
@ लुईस वासरमैन: जावा 9 में, उनके पास privateतरीके हो सकते हैं ।
होल्गर

6
@ डैन पेंट्री: privateविधियाँ वास्तव में इंटरफ़ेस का हिस्सा नहीं हैं, लेकिन defaultकार्यान्वयन के लिए सहायक या निरंतर इनिशियलाइज़र के रूप में कार्य कर सकती हैं । ध्यान दें कि वे पहले से ही जावा 8 में मौजूद हैं, जैसे, जब आप इंटरफेस के भीतर लैम्ब्डा एक्सप्रेशन का उपयोग privateकरते हैं , तो सिंथेटिक तरीके उत्पन्न होते हैं। तो जावा 9 आपको गैर-सिंथेटिक के लिए उस सुविधा का उपयोग करने की अनुमति देता है, गैर लैम्ब्डा का उपयोग करता है…
Holger

14
@jeaver इंटरफेस और कक्षाओं के बीच का अंतर राज्य बनाम व्यवहार को कम करता है । इंटरफेस व्यवहार कर सकते हैं, लेकिन केवल कक्षाओं में राज्य हो सकते हैं। (फ़ील्ड, कंस्ट्रक्टर, और विधियाँ जैसे बराबरी / हैशकोड राज्य के बारे में हैं।)
ब्रायन गोएटज़

26

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

यदि आपको defaultलैम्बदास के कारण पेश किए गए दावे के बारे में कुछ आश्वस्त करने की आवश्यकता है , तो ध्यान दें कि 2009 में मार्क रेनहोल्ड द्वारा प्रोजेक्ट लैंबडा के स्ट्रॉ मैन प्रस्ताव का उल्लेख किया गया है, जिसमें लैम्बदास का समर्थन करने के लिए एक अनिवार्य विशेषता के रूप में 'एक्सटेंशन विधियों' का उल्लेख किया गया है।

यहाँ एक उदाहरण अवधारणा को प्रदर्शित करता है:

interface Operator {
    int operate(int n);
    default int inverse(int n) {
        return -operate(n);
    }
}

public int applyInverse(int n, Operator operator) {
    return operator.inverse(n);
}

applyInverse(3, n -> n * n + 7);

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


8
यह वास्तव में सही नहीं है। लैम्ब्डा निकटस्थ कारण हो सकता है, लेकिन वे वास्तव में सिर्फ तिनके थे जो ऊंट की पीठ को तोड़ते थे। वास्तविक प्रेरणा इंटरफ़ेस विकास को सक्षम करने (मौजूदा इंटरफेस को नए व्यवहार का समर्थन करने के लिए अनुकूल रूप से विकसित करने की अनुमति) थी; लैंबडास वह कारक हो सकता है जिसने इस आवश्यकता को सामने लाया, लेकिन यह सुविधा इससे अधिक सामान्य है।
ब्रायन गोएटज़

@BrianGoetz: IMHO, Java और .NET, दोनों को बहुत फायदा होगा, जिसमें डिफ़ॉल्ट तरीके गेट-गो से मौजूद थे। यदि केवल इंटरफ़ेस सदस्यों के उपयोग से इंटरफ़ेस के किसी भी कार्यान्वयन पर कुछ सामान्य ऑपरेशन किए जा सकते हैं, लेकिन कुछ कार्यान्वयन की संभावना उन्हें करने का अधिक कुशल तरीका होगा, इंटरफ़ेस को उन कार्यों के लिए तरीकों को परिभाषित करना चाहिए और उनके लिए डिफ़ॉल्ट कार्यान्वयन प्रदान करना चाहिए। डिफ़ॉल्ट कार्यान्वयन को निर्दिष्ट करने में असमर्थता ने ऐसे तरीकों से इंटरफेस को हटाने के लिए दबाव प्रेरित किया है, और बाद में उन्हें जोड़ना उनके लिए असंभव बना दिया है।
सुपरकैट

@BrianGoetz मैं मानता हूं कि डिफ़ॉल्ट तरीकों में लैम्बडा से परे महत्वपूर्ण मूल्य है। लेकिन मुझे लगता है कि आप उन्हें शामिल करने के निर्णय को चलाने के लिए उस व्यापक मूल्य को दे सकते हैं किसी भी संदर्भ में दिलचस्पी होगी। मेरा पढ़ना यह है कि लंबोदर प्राथमिक कारण थे (यही वजह है कि मैंने अपने उत्तर में 'प्राथमिक रूप से' शब्द का इस्तेमाल किया है)।
स्प्रिंटर

2
शायद यह दस्तावेज़ मदद करेगा: cr.openjdk.java.net/~briangoetz/lambda/lambda-state-final.html । धारा 10 स्पष्ट रूप से कहती है: "डिफ़ॉल्ट तरीकों का उद्देश्य (जिसे पहले वर्चुअल एक्सटेंशन विधियों या डिफेंडर विधियों के रूप में संदर्भित किया जाता है) उनके प्रारंभिक प्रकाशन के बाद इंटरफेस को संगत तरीके से विकसित करने में सक्षम बनाता है।" लैंबडा-फ्रेंडली तरीकों को तब इंटरफेस इवोल्यूशन के दृष्टांत के रूप में उद्धृत किया जाता है।
ब्रायन गोएटज़

2
@ कार्तिक आप गलत सवाल पूछ रहे हैं! हम "सही ढंग से प्रोग्राम को पार्स करने के लिए कंपाइलर की क्या आवश्यकता है" के आधार पर वाक्यविन्यास का चयन नहीं करते हैं; हम इसे "क्या प्रोग्रामर का इरादा पाठकों को तुरंत स्पष्ट कर देगा के आधार पर चुनते हैं।" हम पहले यूजर्स के लिए डिजाइन करते हैं, और दूसरे में कंपाइलर्स के लिए (और जब यूजर्स की बात आती है, तो हम पहले पढ़ने के लिए डिजाइन करते हैं, और
ब्रायन गोएट्ज

16

जावा 8 में एक नया कॉन्सेप्ट पेश किया गया है जिसे डिफॉल्ट मेथड्स कहा जाता है। डिफ़ॉल्ट विधियाँ वे विधियाँ हैं जिनमें कुछ डिफ़ॉल्ट कार्यान्वयन है और मौजूदा कोड को तोड़ने के बिना इंटरफेस को विकसित करने में मदद करता है। एक उदाहरण देखें:

 public interface SimpleInterface {
    public void doSomeWork();

    //A default method in the interface created using "default" keyword

    default public void doSomeOtherWork(){

    System.out.println("DoSomeOtherWork implementation in the interface");
       }
    }

 class SimpleInterfaceImpl implements SimpleInterface{

  @Override
  public void doSomeWork() {
  System.out.println("Do Some Work implementation in the class");
   }

 /*
  * Not required to override to provide an implementation
  * for doSomeOtherWork.
  */

 public static void main(String[] args) {
   SimpleInterfaceImpl simpObj = new SimpleInterfaceImpl();
   simpObj.doSomeWork();
   simpObj.doSomeOtherWork();
      }
   }

और आउटपुट है:


इंटरफ़ेस में क्लास DoSomeOtherWork कार्यान्वयन में कुछ कार्य कार्यान्वयन करें


16

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

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Processor {
    String value() default "AMD";
}

यह उपयोग जावा 8 के परिचय के साथ अतिभारित किया गया था ताकि एक इंटरफेस में डिफ़ॉल्ट विधि को परिभाषित किया जा सके।

कुछ और जिसे अनदेखा किया गया था: जिस कारण default class MyClass {}से अमान्य घोषित किया गया है वह इस कारण से है कि कक्षाएं बिल्कुल घोषित की जाती हैं । उस भाषा में कोई प्रावधान नहीं है जो उस कीवर्ड को वहां प्रदर्शित करने की अनुमति देता है। यह इंटरफ़ेस विधि घोषणाओं के लिए प्रकट होता है , हालांकि।


3

नया जावा 8 फीचर ( डिफॉल्ट मेथड्स ) एक इंटरफेस को तब लागू करने की अनुमति देता है जब defaultकीवर्ड के साथ उसका लेबल लगाया जाता है ।

उदाहरण के लिए:

interface Test {
    default double getAvg(int avg) {
        return avg;
    }
}
class Tester implements Test{
 //compiles just fine
}

इंटरफ़ेस टेस्ट डिफ़ॉल्ट कीवर्ड का उपयोग करता है जो इंटरफ़ेस को उन वर्गों में लागू करने की आवश्यकता के बिना विधि का डिफ़ॉल्ट कार्यान्वयन प्रदान करने की अनुमति देता है जो इंटरफ़ेस का उपयोग करता है।

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

तथ्य और प्रतिबंध:

1-मई केवल एक इंटरफेस के भीतर घोषित किया जाना चाहिए और एक वर्ग या सार वर्ग के भीतर नहीं।

2-एक शरीर प्रदान करना चाहिए

3-यह एक इंटरफ़ेस में उपयोग किए जाने वाले अन्य सामान्य तरीकों के रूप में सार्वजनिक या सार नहीं माना जाता है।


3

एक इंटरफ़ेस में डिफ़ॉल्ट तरीके हमें पुराने कोड को तोड़ने के बिना नई कार्यक्षमता जोड़ने की अनुमति देते हैं।

जावा 8 से पहले, यदि एक इंटरफ़ेस में एक नई विधि जोड़ी गई थी, तो उस इंटरफ़ेस की सभी कार्यान्वयन कक्षाएं उस नई पद्धति को ओवरराइड करने के लिए बाध्य थीं, भले ही उन्होंने नई कार्यक्षमता का उपयोग न किया हो।

जावा 8 के साथ, हम defaultविधि लागू करने से पहले कीवर्ड का उपयोग करके नई पद्धति के लिए डिफ़ॉल्ट कार्यान्वयन जोड़ सकते हैं ।

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

उदाहरण

public interface YourInterface {
    public void doSomeWork();

    //A default method in the interface created using "default" keyword
    default public void doSomeOtherWork(){

    System.out.println("DoSomeOtherWork implementation in the interface");
       }
    }

    class SimpleInterfaceImpl implements YourInterface{

     /*
     * Not required to override to provide an implementation
     * for doSomeOtherWork.
     */
      @Override
      public void doSomeWork() {
  System.out.println("Do Some Work implementation in the class");
   }

 /*
  * Main method
  */
 public static void main(String[] args) {
   SimpleInterfaceImpl simpObj = new SimpleInterfaceImpl();
   simpObj.doSomeWork();
   simpObj.doSomeOtherWork();
      }
   }

2

जावा ™ ट्यूटोरियल में एक बहुत अच्छी व्याख्या पाई गई है , स्पष्टीकरण का हिस्सा इस प्रकार है:

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

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


1

डिफ़ॉल्ट विधियाँ आपको अपने ऐप्स के इंटरफेस में नई कार्यक्षमता जोड़ने में सक्षम बनाती हैं। इसका उपयोग बहु विरासत के लिए भी किया जा सकता है । डिफ़ॉल्ट तरीकों के अलावा, आप इंटरफेस में स्थिर तरीकों को परिभाषित कर सकते हैं। इससे आपको सहायक विधियों को व्यवस्थित करने में आसानी होती है

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