जावा में डिफॉल्ट तरीके से कॉल करना


247

जावा 8 मौजूदा कार्यान्वयन को संशोधित करने की आवश्यकता के बिना इंटरफेस का विस्तार करने की क्षमता प्रदान करने के लिए डिफ़ॉल्ट तरीकों का परिचय देता है ।

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

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

class B implements A {
    @Override
    public void foo() {
        System.out.println("B.foo");
    }
    public void afoo() {
        // how to invoke A.foo() here?
    }
}

ऊपर दिए गए कोड को ध्यान में रखते हुए, आप A.foo()कक्षा B की विधि से कैसे कॉल करेंगे ?


क्या आप मुझे बता सकते हैं कि आपके इंटरफ़ेस (ए) के अंदर आपके फू () पद्धति पर कार्यान्वयन क्यों है?
मैकीज साइगन

20
@MaciejCygan यह जावा 8 में अनुमति है
रोहित जैन

जवाबों:


330

इस लेख के अनुसार आप इंटरफ़ेस Aका उपयोग करते हुए डिफ़ॉल्ट विधि का उपयोग करते हैं

A.super.foo();

इसका उपयोग निम्नानुसार किया जा सकता है (इंटरफेस को मानते हुए Aऔर Cदोनों में डिफ़ॉल्ट तरीके हैं foo())

public class ChildClass implements A, C {
    @Override    
    public void foo() {
       //you could completely override the default implementations
       doSomethingElse();
       //or manage conflicts between the same method foo() in both A and C
       A.super.foo();
    }
    public void bah() {
       A.super.foo(); //original foo() from A accessed
       C.super.foo(); //original foo() from C accessed
    }
}

Aऔर Cदोनों .foo()तरीके हो सकते हैं और विशिष्ट डिफ़ॉल्ट कार्यान्वयन को चुना जा सकता है या आप अपनी नई foo()विधि के हिस्से के रूप में एक (या दोनों) का उपयोग कर सकते हैं । आप अपने कार्यान्वयन वर्ग में अन्य विधियों में डिफ़ॉल्ट संस्करणों तक पहुंचने के लिए समान सिंटैक्स का उपयोग कर सकते हैं।

विधि मंगलाचरण वाक्यविन्यास का औपचारिक विवरण JLS के अध्याय 15 में पाया जा सकता है ।


14
यह भी ध्यान दें कि अगर A extends SomeOtherInterface, और SomeOtherInterfaceहै default Type method(), तो आप SomeOtherInterface.super.method()चाइल्डक्लास से कॉल नहीं कर सकते । आप केवल ChildClass's implementsउपवाक्य में संलग्न इंटरफेस के डिफ़ॉल्ट तरीकों को कॉल कर सकते हैं , न कि उनके मूल इंटरफेस के तरीकों को।'
ग्वलासोव

1
@Susika अच्छी बात है, वहाँ कोई नहीं है super.super.someMethod();(क्योंकि यह भयानक होगा)
रिचर्ड टिंगल

@gvlasov अच्छा बिंदु है, लेकिन एक बच्चे के इंटरफेस से माता-पिता के इंटरफ़ेस की डिफ़ॉल्ट विधि का उपयोग कैसे करें, क्या यह संभव है ?? अद्यतन .......... हाँ संभव है, अधिक ठोस स्पष्टीकरण यहाँ stackoverflow.com/a/24280376/3791156
रागु

@ रीचार्डिंगल निर्दोष उत्तर!
गौरव

17

नीचे दिया गया कोड काम करना चाहिए।

public class B implements A {
    @Override
    public void foo() {
        System.out.println("B.foo");
    }

    void aFoo() {
        A.super.foo();
    }

    public static void main(String[] args) {
        B b = new B();
        b.foo();
        b.aFoo();
    }
}

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

आउटपुट:

B.foo
A.foo

मुझे लगता है कि यह सबसे अच्छा उदाहरण है जो उपरोक्त प्रश्न का वर्णन करता है। धन्यवाद
हेमंत Peela

8

यह उत्तर मुख्य रूप से उन उपयोगकर्ताओं के लिए लिखा गया है जो प्रश्न 45047550 से आ रहे हैं, जो बंद है।

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

class ParentClass {
    public void hello() {
        System.out.println("Hello ParentClass!");
    }
}

interface InterfaceFoo {
    default public void hello() {
        System.out.println("Hello InterfaceFoo!");
    }
}

interface InterfaceBar {
    default public void hello() {
        System.out.println("Hello InterfaceBar!");
    }
}

public class Example extends ParentClass implements InterfaceFoo, InterfaceBar {
    public void hello() {
        super.hello(); // (note: ParentClass.super is wrong!)
        InterfaceFoo.super.hello();
        InterfaceBar.super.hello();
    }

    public static void main(String[] args) {
        new Example().hello();
    }
}

आउटपुट:

हेलो पेरेंटक्लास!
हेलो इंटरफ़ेसफू!
हैलो इंटरफ़ेसबेर!


3

आपको किसी इंटरफ़ेस की डिफ़ॉल्ट विधि को ओवरराइड करने की आवश्यकता नहीं है। बस इसे निम्नलिखित की तरह कहें:

public class B implements A {

    @Override
    public void foo() {
        System.out.println("B.foo");
    }

    public void afoo() {
        A.super.foo();
    }

    public static void main(String[] args) {
       B b=new B();
       b.afoo();
    }
}

आउटपुट:

A.foo


9
ओपी कहता है: "[क्या यह संभव है] किसी विधि के डिफ़ॉल्ट कार्यान्वयन को स्पष्ट रूप से लागू करना संभव है जब उस विधि को ओवरराइड किया गया हो"
dasblinkenlight
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.