इंटरफ़ेस में परिभाषित विधि का "डिफ़ॉल्ट" कार्यान्वयन क्या है?


91

संग्रह इंटरफ़ेस में मुझे एक विधि मिली जिसका नाम removeIf()है उसका कार्यान्वयन।

default boolean removeIf(Predicate<? super E> filter) {
    Objects.requireNonNull(filter);  
    boolean removed = false;  
    final Iterator<E> each = iterator();   
    while (each.hasNext()) {  
        if (filter.test(each.next())) {  
            each.remove();  
            removed = true;  
        }  
    }  
    return removed;  
}  

मैं जानना चाहता हूं कि क्या इंटरफ़ेस में विधि बॉडी को परिभाषित करने का कोई तरीका है? कीवर्ड
क्या है defaultऔर यह कैसे काम करता है?



संबंधित पोस्ट stackoverflow.com/questions/31578427/…
रवि

जवाबों:


162

से https://dzone.com/articles/interface-default-methods-java

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

public interface A {
    default void foo(){
       System.out.println("Calling A.foo()");
    }
}

public class ClassAB implements A {
}

एक सामान्य सवाल है जो लोग पहली बार नई सुविधा के बारे में सुनते समय डिफ़ॉल्ट तरीकों के बारे में पूछते हैं:

क्या होगा यदि वर्ग दो इंटरफेस को लागू करता है और दोनों इंटरफेस एक ही हस्ताक्षर के साथ एक डिफ़ॉल्ट विधि को परिभाषित करते हैं?

इस स्थिति को स्पष्ट करने के लिए उदाहरण:

public interface A {  
    default void foo(){  
        System.out.println("Calling A.foo()");  
    }  
}

public interface B {
    default void foo(){
        System.out.println("Calling B.foo()");
    }
}


public class ClassAB implements A, B {

}  

यह कोड निम्नलिखित परिणाम के साथ संकलन करने में विफल रहता है:

java: class Clazz inherits unrelated defaults for foo() from types A and B

इसे ठीक करने के लिए, Clazz में, हमें इसे परस्पर विरोधी पद्धति को ओवरराइड करके हल करना होगा:

public class Clazz implements A, B {
    public void foo(){}
}

लेकिन क्या होगा अगर हम अपने स्वयं के कार्यान्वयन के बजाय इंटरफ़ेस ए से विधि फू () के डिफ़ॉल्ट कार्यान्वयन को कॉल करना चाहते हैं।

निम्नानुसार ए # फू को संदर्भित करना संभव है:

public class Clazz implements A, B {
    public void foo(){
       A.super.foo();
    }
}

18
धन्यवाद, वास्तव में अच्छा प्रदर्शन। आपने मुझे पूछने का मौका देने से पहले मेरे सभी सवालों के जवाब दिए।
जेफ हचिंस

इसके बजाय अमूर्त का उपयोग क्यों नहीं करते?
एस्टोल्फो होशर

1
@AstolfoHoscher आप केवल एक वर्ग का विस्तार कर सकते हैं, लेकिन आप कई इंटरफ़ेस लागू कर सकते हैं।
चार्ल्स वुड

49

उन विधियों को डिफ़ॉल्ट विधियाँ कहा जाता है। डिफ़ॉल्ट विधि या डिफेंडर विधि जावा 8 में नई गयी सुविधाओं में से एक है ।

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

इसलिए, यदि आपके पास एक डिफ़ॉल्ट विधि के साथ एक इंटरफ़ेस है:

public interface Hello {
    default void sayHello() {
        System.out.println("Hello");
    }
}

निम्न वर्ग पूरी तरह से मान्य है:

public class HelloImpl implements Hello {

}

यदि आप एक उदाहरण बनाते हैं HelloImpl:

Hello hello = new HelloImpl();
hello.sayHello();  // This will invoke the default method in interface

उपयोगी कड़ियाँ:


तो यह ठीक है अगर एक वर्ग एक इंटरफ़ेस लागू करता है और इसे लागू करने की विधि नहीं है? जहां तक ​​Java7 का संबंध है जो मैं उपयोग कर रहा हूं, इसकी अनुमति नहीं है।
अनिकेत ठाकुर

2
@AniketThakur। यह जावा 8 से पहले अनुमति नहीं है। यह सुविधा केवल जावा 8 में जोड़ी गई है। आप अपने कार्यान्वयन वर्ग में डिफ़ॉल्ट विधियों के कार्यान्वयन को देने से बच सकते हैं ।
रोहित जैन

1
@PawanMishra। मेरी पिछली टिप्पणी देखें। नहीं, आपको क्लास को लागू करने में डिफ़ॉल्ट इंटरफ़ेस विधियों के कार्यान्वयन की आवश्यकता नहीं है।
रोहित जैन

1
@PawanMishra आप इसे ओवरराइड कर सकते हैं। कोई प्रतिबंध नहीं है जैसे कि आपको केवल डिफ़ॉल्ट कार्यान्वयन का उपयोग करने की आवश्यकता है।
अनिकेत ठाकुर

4
एक आगे कदम है जो अंत में कई विरासत से हैरान होने से बचना होगा!
Xtreme बाइकर

17

मैंने थोड़ा शोध किया और मैंने निम्नलिखित पाया। उम्मीद है की यह मदद करेगा।

मौजूदा समस्या

सामान्य इंटरफ़ेस विधियों को सार के रूप में घोषित किया जाता है और इंटरफ़ेस को लागू करने वाले वर्ग में परिभाषित किया जाना चाहिए। यह This बोझ ’श्रेणी के कार्यान्वयनकर्ता को हर घोषित पद्धति को लागू करने की जिम्मेदारी के साथ है। इससे भी महत्वपूर्ण बात यह है कि इसका मतलब यह भी है कि 'प्रकाशन' के बाद एक इंटरफ़ेस का विस्तार संभव नहीं है। अन्यथा, सभी कार्यान्वयनकर्ताओं को अपने कार्यान्वयन को अनुकूलित करना होगा, बैकवर्ड स्रोत और बाइनरी संगतता को तोड़ना होगा।

जावा 8 में अपनाया गया समाधान

इन समस्याओं से निपटने के लिए, JDK 8 की नई विशेषताओं में से एक डिफ़ॉल्ट तरीकों के साथ मौजूदा इंटरफेस का विस्तार करने की संभावना है। डिफ़ॉल्ट तरीके न केवल घोषित किए जाते हैं, बल्कि इंटरफ़ेस में भी परिभाषित किए जाते हैं।

नोट करने के लिए महत्वपूर्ण बिंदु

  1. कार्यान्वयनकर्ता वर्ग को लागू करने में डिफ़ॉल्ट विधियों को लागू नहीं करने का विकल्प चुन सकते हैं।
  2. कार्यान्वयनकर्ता अभी भी डिफ़ॉल्ट विधियों को ओवरराइड कर सकते हैं, जैसे नियमित गैर-अंतिम वर्ग के तरीकों को उपवर्गों में ओवरराइड किया जा सकता है।
  3. एब्सट्रैक्ट क्लासेज (फिर से) डिफॉल्ट मेथड्स को अमूर्त घोषित कर सकती हैं, सबक्लासेस को विधि को फिर से लागू करने के लिए मजबूर करती है (कभी-कभी इसे 'रि-एब्स्ट्रक्शन' भी कहा जाता है)।
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.