2016-03-03 8 views
5

यहाँ एक सरल मेरी समस्या दिखा उदाहरण है:डिफ़ॉल्ट इंटरफ़ेस विधि को लागू करना चाहिए?

import java.util.List; 

public interface SingleTask extends List<Runnable>, Runnable { 
    default Runnable get(final int x) { 
     if (x != 0) { 
      throw new IndexOutOfBoundsException(); 
     } 
     return this; 
    } 

    default int size() { 
     return 1; 
    } 
} 

import java.util.AbstractList; 

public class MyTask extends AbstractList<Runnable> implements SingleTask { 
    @Override 
    public void run() { 
     System.out.println("hello"); 
    } 
} 

SingleTask में मैं तरीकों get और size, जो AbstractList से केवल सार तरीके हैं के लिए कार्यान्वयन प्रदान करते हैं।

The type MyTask must implement the inherited abstract method AbstractCollection.size()

या

MyTask.java:3: error: MyTask is not abstract and does not override abstract method get(int) in AbstractList

(संकलक के आधार पर): हालांकि, जब मैं संकलन MyTask, मैं अभी भी तरह त्रुटियों मिलता है। मैं निश्चित रूप से कर रहा हूँ,, जावा का उपयोग कर 8.

तो मैं दो प्रश्न हैं:

  1. मैं इन त्रुटियों को क्यों मिल रहा है? मैं इसे डिफ़ॉल्ट कार्यान्वयन को पहचानने की उम्मीद कर रहा था।
  2. यदि ऐसा नहीं लगता है, तो पूरे कोड की प्रतिलिपि किए बिना MyTask में उन दो विधियों का उपयोग करने का सबसे आसान तरीका क्या है?
+1

अपने कार्यों को 'सूची ' का विस्तार न करें (वैसे भी इसका अर्थ क्या है?), इसके बजाय 'सार्वजनिक सूची getRunnables(); विधि के साथ एक इंटरफ़ेस' कार्य 'बनाएं। विफल होने के कारण, बस इंटरफ़ेस के बजाय 'सिंगलटास्क' को एक अमूर्त वर्ग बनाएं। – biziclop

+1

यह ध्यान देने योग्य है कि ग्रहण 'आकार()' पर लागू नहीं हो रहा है: यह शायद ग्रहण बग है। 'जावैक' 1.8.0_51 'प्राप्त (int)' पर लागू हो रहा है, यह लागू नहीं किया जा रहा है और यह सही है: इसे लागू नहीं किया गया है। – Tunaki

+0

@biziclop यह कार्यों की एक सूची माना जाता है; SingleTask एक सिंगलटन कार्यान्वयन – aditsu

उत्तर

6

SingleTask कार्यान्वयन करने वालों जबरदस्ती भी List के सभी तरीकों को लागू करने के बहुत ही सुंदर नहीं है, और डिफ़ॉल्ट तरीकों विशेषता की तरह संस्थाओं, जो आपके SingleTask इंटरफ़ेस की तरह दिखता है परिभाषित करने के लिए प्रयोग की जाने वाली नहीं होती हैं।

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

और यह वास्तव में यहाँ क्या हो रहा है: के बाद से AbstractList स्पष्ट abstract रूप get() और size() वाणी है, इसका मतलब SingleTask बल्कि डिफ़ॉल्ट कार्यान्वयन आप एक superinterface में हो सकने वाले की तुलना में, उन्हें प्राप्त कर लेगा।

JLS 8.4.8:

A class C inherits from its direct superclass and direct superinterfaces all abstract and default (§9.4) methods m for which all of the following are true:

...

  • No concrete method inherited by C from its direct superclass has a signature that is a subsignature of the signature of m.

कि सभी असर को ध्यान में सरल समाधान शायद यह है:

public abstract class SingleTask extends AbstractList<Runnable> implements Runnable { 
    @Override 
    public final Runnable get(final int x) { 
     if (x != 0) { 
      throw new IndexOutOfBoundsException(); 
     } 
     return this; 
    } 

    @Override 
    public final int size() { 
     return 1; 
    } 

    @Override 
    public abstract void run(); 
} 

इसका दोष यह है कि अपने कार्यों को SingleTask का विस्तार करना होगा और इस तरह कुछ और विस्तार नहीं कर सकते, प्लस साइड पर हालांकि उन्हें कार्य के साथ सौदा करने की आवश्यकता नहीं है, यह भी List है, उन्हें केवल run() लागू करने की आवश्यकता है।

हालांकि लंबे समय तक, मैं विरासत पर रचना पसंद करूंगा, और कार्यों को केवल एक होने के बजाए रननेबल्स की सूची लौटा दूंगा।

+0

देखें मैं SingleTask कार्यान्वयन करने के लिए मजबूर कर नहीं किया गया था भी AbstractList विस्तार करने के लिए, लेकिन ऐसा लगता है कि आप कर रहे हैं। इसके अलावा, आपने सिंगलटास्क को एक वर्ग बनाया है, जिसका अर्थ है कि यदि मैं इसका उपयोग करना चाहता हूं तो मैं एक अलग वर्ग का विस्तार नहीं कर सकता। और आपने मेरे पहले प्रश्न का उत्तर देने का भी प्रयास नहीं किया था। – aditsu

+1

@aditsu 'मैं सिंगलटास्क कार्यान्वयनकर्ताओं को सारसूची 'हां, आप ऐसा करने के लिए मजबूर नहीं कर रहा था, और यही कारण है कि समस्याएं पैदा कर रही हैं। मैं इसे भी कवर करने के लिए अपना जवाब संपादित करूंगा। – biziclop

+0

गलत, मेरे कोड के साथ, सिंगलटास्क कार्यान्वयनकर्ताओं को केवल सूची के तरीकों को लागू करने की आवश्यकता है। सारसूची के बारे में सिंगलटास्क में कुछ भी नहीं है! – aditsu

2
  1. Why am I getting these errors? I was expecting it to recognize the default implementations.

मुझे लगता है कि @biziclop सही ढंग से his answer में शामिल है। संक्षेप में, AbstractListget(int) और size() अमूर्त के रूप में घोषित करता है, SingleTask में आपके डिफ़ॉल्ट कार्यान्वयन पर ये प्राथमिकता है।

  1. If it's not supposed to work like that, then what's the simplest way to use those two methods in MyTask without copying the whole code?

सबसे आसान, MyTask में get(int) और size() तरीकों ओवरराइड करने के लिए इतना है कि वे SingleTask इंटरफ़ेस में अपने डिफ़ॉल्ट तरीकों के प्रतिनिधि होगा:

public class MyTask extends AbstractList<Runnable> implements SingleTask { 

    @Override 
    public void run() { 
     System.out.println("hello"); 
    } 

    @Override 
    public Runnable get(int index) { 
     return SingleTask.super.get(index); 
    } 

    @Override 
    public int size() { 
     return SingleTask.super.size(); 
    } 
} 
इस दृष्टिकोण के साथ

, आप delegating की तरह होगाSingleTask में आपकी डिफ़ॉल्ट विधियों के लिए। मुझे नहीं लगता कि यह एक बुरी बात है (कम से कम, आपको एक विशेषता का उपयोग करने की आवश्यकता नहीं है)। इसके अलावा, इन विधियों को लिखना समझ में आता है, ताकि आप यह चुन सकें कि कौन सा इंटरफ़ेस डिफ़ॉल्ट कार्यान्वयन प्रदान करता है।

संबंधित मुद्दे