Java Language
डिफ़ॉल्ट तरीके
खोज…
परिचय
जावा 8 में शुरू की गई डिफ़ॉल्ट विधि , डेवलपर्स को इस इंटरफ़ेस के मौजूदा कार्यान्वयन को तोड़ने के बिना एक इंटरफ़ेस में नए तरीकों को जोड़ने की अनुमति देती है। यह इंटरफ़ेस को एक कार्यान्वयन को परिभाषित करने की अनुमति देने के लिए लचीलापन प्रदान करता है जिसका उपयोग डिफ़ॉल्ट के रूप में किया जाएगा जब एक वर्ग जो उस इंटरफ़ेस को लागू करता है, उस पद्धति का कार्यान्वयन प्रदान करने में विफल रहता है।
वाक्य - विन्यास
- सार्वजनिक डिफ़ॉल्ट शून्य विधि नाम () {/ * विधि निकाय * /}
टिप्पणियों
डिफ़ॉल्ट तरीके
- एक इंटरफ़ेस के भीतर इस्तेमाल किया जा सकता है, इसे लागू करने के लिए मौजूदा उपवर्गों को मजबूर किए बिना एक व्यवहार पेश करना।
- उपवर्गों द्वारा या उप-इंटरफ़ेस द्वारा ओवरराइड किया जा सकता है।
- Java.lang.Object क्लास में तरीकों को ओवरराइड करने की अनुमति नहीं है।
- यदि एक वर्ग एक से अधिक इंटरफ़ेस को लागू करता है, तो प्रत्येक पूर्णांक से समान विधि हस्ताक्षर के साथ डिफ़ॉल्ट तरीके विरासत में मिलते हैं, तो इसे ओवरराइड करना चाहिए और अपना स्वयं का इंटरफ़ेस प्रदान करना चाहिए जैसे कि वे डिफ़ॉल्ट तरीके नहीं थे (कई वंशानुक्रम को हल करने के भाग के रूप में)।
- यद्यपि मौजूदा कार्यान्वयनों को तोड़ने के बिना एक व्यवहार का परिचय देने का इरादा है, मौजूदा उपवर्गों को उसी विधि हस्ताक्षर के साथ एक स्थिर विधि के साथ जोड़ा जाता है क्योंकि नई शुरू की गई डिफ़ॉल्ट विधि अभी भी टूट जाएगी। हालाँकि यह एक सुपरक्लास में एक इंस्टेंस मेथड शुरू करने के मामले में भी सच है।
स्थैतिक तरीके
- एक इंटरफेस के भीतर इस्तेमाल किया जा सकता है, मुख्य रूप से डिफ़ॉल्ट तरीकों के लिए एक उपयोगिता विधि के रूप में उपयोग करने का इरादा है।
- उपवर्गों या उप-इंटरफ़ेस द्वारा ओवरराइड नहीं किया जा सकता (यह उनके लिए छिपा हुआ है)। हालांकि जैसा कि अभी भी स्थैतिक तरीकों के साथ है, प्रत्येक वर्ग या इंटरफ़ेस का अपना हो सकता है।
- Java.lang.Object वर्ग में उदाहरण के तरीकों को ओवरराइड करने की अनुमति नहीं है (जैसा कि वर्तमान में उपवर्गों के लिए भी मामला है)।
नीचे एक तालिका उप-वर्ग और सुपर-क्लास के बीच बातचीत का सारांश है।
- | SUPER_CLASS-उदाहरण-विधि | SUPER_CLASS-स्थिर-विधि |
---|---|---|
SUB_CLASS-उदाहरण-विधि | ओवरराइड | उत्पन्न करता है-compiletime त्रुटि |
SUB_CLASS-स्थिर-विधि | उत्पन्न करता है-compiletime त्रुटि | खाल |
नीचे एक तालिका है जो इंटरफ़ेस और कार्यान्वयन-वर्ग के बीच की बातचीत को सारांशित करती है।
- | इंटरफ़ेस-default-विधि | इंटरफ़ेस-स्थिर-विधि |
---|---|---|
IMPL_CLASS-उदाहरण-विधि | ओवरराइड | खाल |
IMPL_CLASS-स्थिर-विधि | उत्पन्न करता है-compiletime त्रुटि | खाल |
संदर्भ:
- http://www.journaldev.com/2752/java-8-interface-changes-static-method-default-method
- https://docs.oracle.com/javase/tutorial/java/IandI/override.html
डिफ़ॉल्ट विधियों का मूल उपयोग
/**
* Interface with default method
*/
public interface Printable {
default void printString() {
System.out.println( "default implementation" );
}
}
/**
* Class which falls back to default implementation of {@link #printString()}
*/
public class WithDefault
implements Printable
{
}
/**
* Custom implementation of {@link #printString()}
*/
public class OverrideDefault
implements Printable {
@Override
public void printString() {
System.out.println( "overridden implementation" );
}
}
निम्नलिखित कथन
new WithDefault().printString();
new OverrideDefault().printString();
इस उत्पादन का उत्पादन करेंगे:
default implementation
overridden implementation
डिफ़ॉल्ट विधि के भीतर अन्य इंटरफ़ेस विधियों तक पहुँचना
आप अपने डिफ़ॉल्ट विधि के भीतर से अन्य इंटरफ़ेस विधियों का उपयोग कर सकते हैं।
public interface Summable {
int getA();
int getB();
default int calculateSum() {
return getA() + getB();
}
}
public class Sum implements Summable {
@Override
public int getA() {
return 1;
}
@Override
public int getB() {
return 2;
}
}
निम्नलिखित कथन 3 प्रिंट करेगा:
System.out.println(new Sum().calculateSum());
डिफ़ॉल्ट तरीकों का उपयोग इंटरफ़ेस स्थिर तरीकों के साथ भी किया जा सकता है:
public interface Summable {
static int getA() {
return 1;
}
static int getB() {
return 2;
}
default int calculateSum() {
return getA() + getB();
}
}
public class Sum implements Summable {}
निम्नलिखित कथन 3 को भी प्रिंट करेगा:
System.out.println(new Sum().calculateSum());
क्लास को लागू करने से ओवरराइड डिफ़ॉल्ट तरीकों तक पहुँचना
कक्षाओं में, super.foo()
केवल super.foo()
में दिखेगा। यदि आप किसी Fooable.super.foo()
से डिफ़ॉल्ट कार्यान्वयन को कॉल करना चाहते हैं, तो आपको इंटरफ़ेस नाम के साथ super
को अर्हता प्राप्त करने की आवश्यकता है: Fooable.super.foo()
।
public interface Fooable {
default int foo() {return 3;}
}
public class A extends Object implements Fooable {
@Override
public int foo() {
//return super.foo() + 1; //error: no method foo() in java.lang.Object
return Fooable.super.foo() + 1; //okay, returns 4
}
}
डिफ़ॉल्ट विधियों का उपयोग क्यों करें?
इसका सरल उत्तर यह है कि यह आपको मौजूदा कार्यान्वयन को तोड़े बिना मौजूदा इंटरफ़ेस को विकसित करने की अनुमति देता है।
उदाहरण के लिए, आपके पास Swim
इंटरफ़ेस है जिसे आपने 20 साल पहले प्रकाशित किया था।
public interface Swim {
void backStroke();
}
हमने बहुत अच्छा काम किया, हमारा इंटरफ़ेस बहुत लोकप्रिय है, दुनिया भर में उस पर कई कार्यान्वयन हैं और आपके पास उनके स्रोत कोड पर नियंत्रण नहीं है।
public class FooSwimmer implements Swim {
public void backStroke() {
System.out.println("Do backstroke");
}
}
20 वर्षों के बाद, आपने इंटरफ़ेस में नई कार्यक्षमता जोड़ने का निर्णय लिया है, लेकिन ऐसा लगता है कि हमारा इंटरफ़ेस स्थिर है क्योंकि यह मौजूदा कार्यान्वयन को तोड़ देगा।
सौभाग्य से जावा 8 बिल्कुल नई विधि का परिचय देता है जिसे डिफ़ॉल्ट विधि कहा जाता है ।
अब हम Swim
इंटरफ़ेस में नई विधि जोड़ सकते हैं।
public interface Swim {
void backStroke();
default void sideStroke() {
System.out.println("Default sidestroke implementation. Can be overridden");
}
}
अब हमारे इंटरफ़ेस के सभी मौजूदा कार्यान्वयन अभी भी काम कर सकते हैं। लेकिन सबसे महत्वपूर्ण बात यह है कि वे अपने समय में नए जोड़े गए तरीके को लागू कर सकते हैं।
इस परिवर्तन के सबसे बड़े कारणों में से एक और इसके सबसे बड़े उपयोगों में से एक जावा कलेक्शंस फ्रेमवर्क है। ओरेकल एक नहीं जोड़ सके foreach
सभी मौजूदा कोड है जो Iterable कार्यान्वित को तोड़ने के बिना मौजूदा Iterable इंटरफ़ेस करने के लिए विधि। डिफ़ॉल्ट तरीकों को जोड़कर, मौजूदा Iterable कार्यान्वयन डिफ़ॉल्ट कार्यान्वयन को इनहेरिट करेगा।
क्लास, एब्सट्रैक्ट क्लास और इंटरफेस विधि की मिसाल
अमूर्त घोषणाओं सहित कक्षाओं में कार्यान्वयन, सभी इंटरफ़ेस चूक पर पूर्वता लेते हैं।
- सार वर्ग विधि इंटरफ़ेस डिफ़ॉल्ट विधि पर पूर्वता लेता है।
public interface Swim {
default void backStroke() {
System.out.println("Swim.backStroke");
}
}
public abstract class AbstractSwimmer implements Swim {
public void backStroke() {
System.out.println("AbstractSwimmer.backStroke");
}
}
public class FooSwimmer extends AbstractSwimmer {
}
निम्नलिखित कथन
new FooSwimmer().backStroke();
उत्पादन करेंगे
AbstractSwimmer.backStroke
- क्लास विधि इंटरफ़ेस डिफ़ॉल्ट विधि पर पूर्वता लेता है
public interface Swim {
default void backStroke() {
System.out.println("Swim.backStroke");
}
}
public abstract class AbstractSwimmer implements Swim {
}
public class FooSwimmer extends AbstractSwimmer {
public void backStroke() {
System.out.println("FooSwimmer.backStroke");
}
}
निम्नलिखित कथन
new FooSwimmer().backStroke();
उत्पादन करेंगे
FooSwimmer.backStroke
डिफ़ॉल्ट विधि कई विरासत टक्कर
अगले उदाहरण पर विचार करें:
public interface A {
default void foo() { System.out.println("A.foo"); }
}
public interface B {
default void foo() { System.out.println("B.foo"); }
}
यहां एक ही हस्ताक्षर के साथ default
विधि foo
घोषित करने वाले दो इंटरफेस हैं।
यदि आप इन दोनों इंटरफेस को नए इंटरफ़ेस में extend
करने extend
प्रयास करेंगे, तो आपको दो का चुनाव करना होगा, क्योंकि जावा आपको इस टकराव को स्पष्ट रूप से हल करने के लिए मजबूर करता है।
सबसे पहले , आप abstract
रूप में एक ही हस्ताक्षर के साथ विधि foo
घोषित कर सकते हैं, जो A
और B
व्यवहार को ओवरराइड करेगा।
public interface ABExtendsAbstract extends A, B {
@Override
void foo();
}
और जब आप ABExtendsAbstract
को class
में implement
करेंगे तो आपको foo
कार्यान्वयन प्रदान करना होगा:
public class ABExtendsAbstractImpl implements ABExtendsAbstract {
@Override
public void foo() { System.out.println("ABImpl.foo"); }
}
या दूसरा , आप पूरी तरह से नया default
कार्यान्वयन प्रदान कर सकते हैं। आप वर्ग को लागू करने से अधिक डिफ़ॉल्ट तरीकों तक पहुँच कर A
और B
foo
तरीकों के कोड का पुन: उपयोग कर सकते हैं।
public interface ABExtends extends A, B {
@Override
default void foo() { System.out.println("ABExtends.foo"); }
}
और जब आप class
में ABExtends
implement
करेंगे not
तो आपको foo
कार्यान्वयन प्रदान not
करना होगा:
public class ABExtendsImpl implements ABExtends {}