क्या JDK 8 में चूक जावा में कई विरासत का एक रूप है?


83

JDK 8 में आने वाली एक नई सुविधा आपको द्विआधारी संगतता को संरक्षित करते हुए मौजूदा इंटरफ़ेस में जोड़ने की अनुमति देती है।

वाक्य-विन्यास जैसा है

public interface SomeInterface() {
  void existingInterface();
  void newInterface() default SomeClass.defaultImplementation;
}

इस तरह के सभी मौजूदा कार्यान्वयन के लिए SomeInterfaceजब वे इस नए संस्करण में अपग्रेड करते हैं, तो वे अचानक चारों ओर त्रुटियों को संकलित नहीं करते हैं newInterface()

जबकि यह साफ-सुथरा है, तब क्या होता है जब आप दो इंटरफेस लागू कर रहे होते हैं जो दोनों ने एक नया डिफॉल्टेड तरीका जोड़ा है जिसे आपने लागू नहीं किया है? एक उदाहरण से समझाता हूं।

public interface Attendance {
   boolean present() default DefaultAttendance.present;
}

public interface Timeline {
   boolean present() default DefaultTimeline.present;
}

public class TimeTravelingStudent implements Attendance, Timeline {

}

// which code gets called?
new TimeTravelingStudent().present();

क्या इसे अभी तक JDK 8 के हिस्से के रूप में परिभाषित किया गया है?

मैंने जावा देवताओं को यहां कुछ इसी तरह की बात करते हुए पाया http://cs.oswego.edu/pipermail/lambda-lib/2011-Febdays/000068.html , लेकिन इसका निजी मेलिंग सूची का हिस्सा है और मैं उनसे सीधे नहीं पूछ सकता।

इस बारे में अधिक जानकारी के लिए देखें कि चूक को JDK 8 में कैसे इस्तेमाल किया जा रहा है और लैम्ब्डा का समर्थन करने के लिए संग्रह इंटरफ़ेस का विस्तार किया जा रहा है: https://oracleus.wingateweb.com/published/oracleus2011/session/25066/25066_Cho223662.pdf


देखने के लिए वीडियो सत्र यहां है medianetwork.oracle.com/video/player/1113272518001 यह डिजाइनर वर्चुअल एक्सटेंशन नामक सुविधा के बारे में बात कर रहा है। वह इस बारे में भी बात करता है कि यह कैसे पिछड़ी संगतता को नहीं तोड़ता है।
पीटर लॉरी

इसलिए मेरे उदाहरण का उत्तर वर्तमान में आपको एक कंपाइलर त्रुटि है। लेकिन वे अन्य समाधानों के लिए खुले हैं।
प्योरोलॉजिकल ऑक्ट

इस के लिए एक और उपयोगी सामग्री है cr.openjdk.java.net/~briangoetz/lambda/...
MohamedSanaulla

सिडेनोट: इंटरफ़ेस विधियों के डिफ़ॉल्ट कार्यान्वयन के लिए अंतिम वाक्यविन्यास अलग हो गया (बाहरी वर्ग के संदर्भ के बजाय कोड ब्लॉक)।
जोकिम सॉयर

4
जावा में हमेशा कई प्रकार के वंशानुक्रम होते हैं । डिफ़ॉल्ट विधियाँ व्यवहार की कई विरासत को जोड़ती हैं , लेकिन राज्य की नहीं । (C ++ जैसी भाषाओं में राज्य की एकाधिक विरासत जहाँ से सबसे अधिक परेशानी होती है।)
ब्रायन गोएट्ज़

जवाबों:


66

डुप्लिकेट ऑपरेशन का उत्तर है:

एकाधिक वंशानुक्रम समस्या को हल करने के लिए एक ही विधि के नाम और हस्ताक्षर के लिए एक डिफ़ॉल्ट कार्यान्वयन प्रदान करने वाले दो इंटरफेस को लागू करने वाला एक वर्ग विधि का कार्यान्वयन प्रदान करना चाहिए। [पूर्ण लेख]

आपके प्रश्न का मेरा उत्तर है: हां, यह कई प्रकार की विरासत का एक रूप है, क्योंकि आप विभिन्न माता-पिता से व्यवहार विरासत में प्राप्त कर सकते हैं। जो चीज गायब है, वह है उत्तराधिकार की स्थिति, अर्थात गुण।


2
+1: जब कोई संघर्ष होता है, तो यह कम विशिष्ट पर अधिक विशिष्ट कार्यान्वयन लेगा, जिससे आपको यह निर्दिष्ट करने की अनुमति होगी कि यदि कोई संघर्ष है तो यह किसका होना चाहिए।
पीटर लॉरी

@ H-Man2 मुझे नहीं मिला। अगर यह सच है तो इसका मतलब है कि यह द्विआधारी संगतता को तोड़ देगा। अब शायद यह इतना बुरा नहीं है जितना कि कई विरासत को रोकने के लिए द्विआधारी संगतता को तोड़ना, द्विआधारी संगतता को तोड़ना।
प्योरोलॉजिकल ऑक्ट

@PeterLawrey जो मेरे उदाहरण में अधिक विशिष्ट है?
पाइरोलॉजिकल ऑक्ट

@ पेट्रोल: नहीं, यह संगतता को नहीं तोड़ता है, क्योंकि कंपाइलर डिफ़ॉल्ट कार्यान्वयन को सामान्य विधि कॉल में अनुवाद कर सकता है। मुझे लगता है कि यह अधिक मैक्रो है तो वास्तविक वंशानुक्रम है, लेकिन मुल के पहलुओं को अनुकरण कर सकता है। हो सकता है कि पीटर का वीडियो अधिक विस्तृत उत्तर प्रदान करता है।
एच-मैन 2

वास्तव में हम गायब हो गए राज्यों के आसपास प्राप्त कर सकते हैं अमूर्त
गेटर्स और बसने से

8

मुझे पता है कि यह एक पुरानी पोस्ट है, लेकिन मैं इस सामान के साथ काम कर रहा हूं ...

आपको यह बताते हुए कि संकलक से एक त्रुटि होगी:

Its वर्ग TimeTravelingStudent वर्तमान अटेंडेंस के लिए असंबंधित डिफॉल्ट्स विरासत में मिला है (अटेंडेंस और टाइमलाइन संदर्भ से वर्तमान में अस्पष्ट है, दोनों विधि मौजूद है) (टाइमलाइन में मौजूद) और एटेंडेंस मैच में मौजूद विधि ()।


7

कर रहे हैं दो परिदृश्यों:

1) सबसे पहले, इसका उल्लेख किया गया था, जहां कोई सबसे विशिष्ट इंटरफ़ेस नहीं है

public interface A {
   default void doStuff(){ /* implementation */ }
}

public interface B {
   default void doStuff() { /* implementation */ } 
}

public class C implements A, B {
// option 1: own implementation
// OR
// option 2: use new syntax to call specific interface or face compilation error
  void doStuff(){
      B.super.doStuff();
  }
}

2) दूसरा, जब एक अधिक विशिष्ट इंटरफ़ेस है:

   public interface A {
       default void doStuff() { /* implementation */ } 
    }

    public interface B extends A {
       default void doStuff() { /* implementation */ } 
    }

    public class C implements A, B {
    // will use method from B, as it is "closer" to C
    }

4

आपके प्रश्न का मेरा उत्तर है: हां, यह कई प्रकार की विरासत का एक रूप है, क्योंकि आप विभिन्न माता-पिता से व्यवहार विरासत में प्राप्त कर सकते हैं। जो चीज गायब है, वह है उत्तराधिकार की स्थिति, अर्थात गुण।

हां, लेकिन आप अपने इंटरफेस में गेटर्स और सेटर्स जोड़ सकते हैं जो कि कार्यान्वयन कक्षाएं फिर लागू करना होगा। फिर भी, लागू करने वाली कक्षाएं गुण नहीं लेती हैं। इसलिए, AFAICS, यह एक बहु-वंशीय शैली समाधान के बजाय एक विशेषता-शैली समाधान की तरह है।


4

संक्षेप में: यह एक संकलन समय त्रुटि है, इसे क्रियान्वयन में हाथ से विधि को ओवरराइड करना चाहिए।


डिफ़ॉल्ट विधि का उद्देश्य

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

और multiple inheritanceसी ++ की तरह वास्तव में से बचने का इरादा है, यह निश्चित रूप से जावा में डिफ़ॉल्ट विधि का उद्देश्य नहीं है।


ओवरराइड कैसे करें

2 विकल्प:

  • अपने स्वयं के तर्क के साथ, विधि को ओवरराइड करें।
  • विधि को ओवरराइड करें, इंटरफ़ेस के किसी एक तरीके को superफॉर्मेट के माध्यम से कॉल करें :<interface_name>.super.<method_name>();

सुझाव:

  • इंटरफ़ेस से विधि सार्वजनिक रूप से डिफ़ॉल्ट है, इसलिए publicइसे ओवरराइड करते समय कीवर्ड जोड़ना न भूलें ।

2

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


0

"हम तरीकों को कैसे भेदेंगे " एक सवाल था जिसे स्टैकओवरफ़्लो पर रखा गया था और इस सवाल को ठोस तरीकों से संदर्भित किया गया था जावा एक्स 8 में

निम्नलिखित एक उदाहरण है जो उस प्रश्न का उत्तर देना चाहिए:

interface A{
default public void m(){
System.out.println("Interface A: m()");
}
}

interface B{
default public void m(){
System.out.println("Interface B: m()");
}
}

 class C implements A,B { 

 public void m(){
  System.out.println("Concrete C: m()");   
 }

public static void main(String[] args) {
   C aC = new C();
   aC.m();
   new A(){}.m();
   new B(){}.m();
}
}

ऊपर दिए गए क्लास C को इंटरफेस ए और बी के अपने-अपने ठोस तरीके को लागू करना चाहिए :

 public void m(){
  System.out.println("Interface C: m()");   
 }

एक कॉल करने के लिए ठोस कार्यान्वयन एक की विधि एक से विशिष्ट इंटरफेस , आप कर सकते हैं का दृष्टांत इंटरफ़ेस और स्पष्ट रूप से कहते हैं ठोस विधि इस बात का इंटरफ़ेस

उदाहरण के लिए, निम्न कोड इंटरफ़ेस ए से विधि एम () का ठोस कार्यान्वयन कहता है :

new A(){}.m();

उपरोक्त का उत्पादन होगा:

इंटरफ़ेस ए: एम ()


-1

जहां तक ​​मैं इसे देखता हूं, यह कोई बहुविध विरासत नहीं है क्योंकि वे स्टेटलेस हैं। इसलिए आभासी विस्तार विधियाँ पूर्ण वस्तु या वर्ग की कार्यक्षमता का समर्थन नहीं करती हैं।

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