2012-10-24 22 views
8
public <S extends T> List<S> save(Iterable<S> entities) { 
     //... 
} 

मैं निम्नलिखित का उपयोग करते हैं विधिजावा: इस सामान्य विधि को ओवरराइड कैसे करें?

@Override 
public List<MyType> save(Iterable<MyType> structures) { 
    List<MyType> result = new ArrayList<>(); 
    //... 
    return result; 
} 

ओवरराइड करने के लिए मैं त्रुटि निम्न हो:

method does not override or implement a method from a supertype 

name clash: save(Iterable<MyType>) in MyTypeRepositoryImpl and <S>save(Iterable<S>) in SimpleJpaRepository have the same erasure, yet neither overrides the other 
    where S,T are type-variables: 
    S extends T declared in method <S>save(Iterable<S>) 
    T extends Object declared in class SimpleJpaRepository 

मैं यह कैसे हल कर सकते हैं? मुझे सामान्य होने की विधि की आवश्यकता नहीं है और वास्तव में यह नहीं होना चाहिए। क्या मेरा मतलब है कि

@Override 
public <S extends MyType> List<S> save(Iterable<S> structures) { 
    List<S> result = new ArrayList<>(); 
    //... 
    return result; 
} 

विधि MyType की एक नई वस्तु जो सूची में 'उपयुक्त' नहीं है बना सकते हैं के रूप में काम नहीं करेगा।

मैं यह काम कैसे कर सकता हूं?

संपादित करें:

स्पष्टीकरण के लिए। मैं (जो QuerydslJpaRepository द्वारा extented है) वसंत डेटा SimpleJpaRepository के विभिन्न बचाने() पद्धतियों

कक्षा defintions ओवरराइड करने के लिए कोशिश कर रहा हूँ:

public class MyTypeRepositoryImpl 
    extends QueryDslJpaRepository<MyType, Long> 
    implements MyTypeRepository 

@NoRepositoryBean 
public interface MyTypeRepository 
    extends JpaRepository<MyType, Long>, 
    QueryDslPredicateExecutor<MyType> 

और यह (स्प्रिंग डाटा से)

public class QueryDslJpaRepository<T, ID extends Serializable> 
extends SimpleJpaRepository<T, ID> 
implements QueryDslPredicateExecutor<T> 

संपादित करें 2:

विधि प्रत्येक तत्व के लिए सहेजती है (MyType इकाई) और उस विधि में निम्नलिखित तर्क शामिल हैं:

  1. इकाई एक क्षेत्र है जो अद्वितीय है
  2. प्राप्त है कि मान फ़ील्ड और देखें कि क्या है कि मूल्य के साथ इकाई पहले से मौजूद
  3. यदि हाँ है, का उपयोग करें कि इकाई (entityManager.merge करने के लिए कॉल) -> रिटर्न काम नहीं करता है MyType S
  4. यदि कोई नया कोई नहीं बनाता -> यहां नई ऑब्जेक्ट बनाई गई है। जेनेरिक प्रकार

के लिए काम नहीं करता है 4. मैं बस id = null सेट कर सकता हूं और पास ऑब्जेक्ट का उपयोग कर सकता हूं। यह 3.

के लिए काम नहीं करता है इसलिए मुझे बहुत परेशान है कि इस विधि में यह हस्ताक्षर क्यों है। यह मेरे लिए यह अनुपयोगी बनाता है और मुझे नहीं पता कि मैं टी डीएओ का उपयोग कर टी के उप-वर्ग को क्यों बचाऊंगा। बचत विधियां केवल एक ही हैं। अन्य सभी बस टी का उपयोग करते हैं। मैं इसे संकलित करने के लिए बस एस पर डाल सकता हूं लेकिन यह बदसूरत लगता है ... क्योंकि टी से किसी अन्य प्रकार के अपवाद का कारण बनता है।

+0

युक्त कक्षाएं कैसे घोषित की जाती हैं? – assylias

+0

सूची के लिए "संगत" नहीं होने का क्या मतलब है? यह मूल '' पैरामीटर की तरह दिखता है कि वर्ग को –

+0

सबक्लासिंग के साथ चारों ओर मकड़ने के बिना 'इंटरफेसनाम लागू' जैसे कुछ करने के द्वारा उपयोग किया जा सकता है, टिप्पणियों से अन्य उत्तरों और तथ्य यह है कि आप हैं जिस वर्ग पर आपका कोई नियंत्रण नहीं है, मेरा मानना ​​है कि आपको 'सार्वजनिक <एस का उपयोग करने के लिए मजबूर किया जाता है MyType> सूची सहेजें (Iterable संरचनाएं) '। ऐसा इसलिए है क्योंकि ओवरराइड विधि जेनेरिक है और इसलिए ओवरराइडिंग विधि भी होनी चाहिए। –

उत्तर

0

मेरे समाधान एक सेवा वर्ग की जरूरत तर्क करता है बना सकते हैं और भंडार अछूता छोड़ने के लिए सभी लेकिन इस पर हावी नहीं किया गया था काम करता है।

+1

कोई अपराध नहीं है, लेकिन यह आपके प्रश्न का समाधान नहीं है जिसे आपने प्रश्न में बताया है, इसलिए "सर्वश्रेष्ठ" उत्तर भी नहीं। जो आप कर चुके हैं वह एक काम है – asgs

8

किसी अन्य विधि को ओवरराइड करने के लिए इसे ओवरराइड विधि के कम से कम सभी मान्य मानकों पर लागू होना चाहिए। आपकी मूल विधि सामान्य public <S extends T> List<S> save(Iterable<S> entities) है। तो यह किसी भी प्रकार S को स्वीकार करेगा जो T बढ़ाता है। हालांकि आपका ओवरराइड अधिक प्रतिबंधित है क्योंकि यह केवल MyType के संग्रह स्वीकार करेगा, इसलिए यह मान्य ओवरराइड नहीं है।

यदि आप अपने आधार वर्ग MyType को T साथ परिभाषित है, और विधि सिर्फ T स्वीकार किए जाते हैं, और व्युत्पन्न वर्ग T नीचे बंद कर दिया था आप ठीक होना चाहिए।

एक बेहतर उत्तर देने के लिए हमें दो वर्गों के लिए कक्षा घोषणाएं देखने की आवश्यकता है। मैं निम्नलिखित सुझाव है:

class MyClass<T>{ 
    public List<T> save(Iterable<T> entities); 
} 

class OtherClass extends MyClass<MyType>{ 
    public List<MyType> save(Iterable<MyType> entities); 
} 

संपादित करें:

आप आधार वर्ग पर नियंत्रण (ऐसा लगता है जो कि आप नहीं है) की जरूरत नहीं है, तो आप public <S extends MyType> List<S> save(Iterable<S> structures) हस्ताक्षर के साथ फंस रहे हैं। इसका कारण यह है ओवरराइड विधि genericized है और इसलिए overridding विधि भी

1

होना चाहिए के बाद से

public <S extends T> List<S> save(Iterable<S> entities) 

दिया जाता है, अपने ओवरराइड के लिए

public <S extends MyType> List<S> save(Iterable<S> structures) 

होना चाहिए और अपने कार्यान्वयन कि एस का आदर करना चाहिए है MyType का असली उप प्रकार हो सकता है।

  • के बाद से जावा> = 1.5 covariant वापसी प्रकार की अनुमति देता है और List<MyType>List<S extends MyType> की एक उप-प्रकार है, यह ठीक है, लेकिन
  • :

    आपका दृष्टिकोण

    public List<MyType> save(Iterable<MyType> structures) 
    

    एक सही ओवरराइड नहीं है जावा केवल invariant पैरामीटर प्रकारों की अनुमति देता है, लेकिन Iterable<MyType>Iterable<S extends MyType> का एक उप प्रकार है, इसलिए आपका कंपाइलर त्रुटि संदेश।

+0

मैं जिस विधि को ओवरराइड करता हूं उसे घोषित नहीं कर रहा हूं। यह वसंत डेटा से एक मौजूदा वर्ग है। संपादन देखें। –

+0

आईसी, तदनुसार मेरा जवाब अपनाया। – DaveFar

2

यहाँ एक उदाहरण है कि संकलित है और पता चलता है कि यह कैसे उपयोग करने के लिए:

abstract class A<T> { 
    abstract public <S extends T> List<S> save(Iterable<S> entities); 
} 

class B extends A<List<Integer>> { 

    @Override 
    public <S extends List<Integer>> List<S> save(Iterable<S> entities) { 
     return null; 
    } 
} 

class C { 
    public void useIt() { 
     B b = new B(); 
     Iterable<ArrayList<Integer>> it = new ArrayList<ArrayList<Integer>>(); 
     b.save(it); 
    } 
} 

कक्षा A मूल हस्ताक्षर के साथ विधि को परिभाषित करता है। कक्षा B इसे लागू करता है और List<Integer> टाइप पैरामीटर T के लिए चुनता है। और अंत में, कक्षा CIterable वेश्या सामान्य प्रकार के साथ इस विधि का उपयोग List<Integer> का उप-वर्ग है।

+0

मुझे वह मिलता है। लेकिन मुझे की आवश्यकता नहीं है। टी एक निश्चित प्रकार है, उदाहरण के लिए। हमेशा एक ही प्रकार, और टी एक अंतिम कक्षा है।इसके अलावा इनपुट के आधार पर मैं विधि में माईटाइप का एक नया ऑब्जेक्ट बना रहा हूं। Mytype newObject = नया MyType (तर्क); यह एस –

+0

उलझन में काम नहीं करता है। यदि 'टी' के लिए अंतिम श्रेणी का उपयोग किया जाता है तो आपको' एस 'के लिए कक्षा नहीं मिलेगी जो विधि को काफी अनुपयोगी बनाती है (इस मामले के लिए) –

+0

एस को पूरा नहीं करता है? मैं अब भी उलझन में हूँ। : ओ –

3

आप कैसे परिभाषित किया है पर निर्भर करता है, तो निम्न

public class TestGenerics2<T> { 
    public <S extends T> List<S> save(Iterable<S> entities) { 
     return new ArrayList<S>(); 
    } 
} 

public class TestGenerics3 extends TestGenerics2<Number> { 
    @Override 
    public <S extends Number> List<S> save(Iterable<S> entities) { 
     return super.save(entities); 
    } 
}