2012-03-13 13 views
9

मैं इस दो अंतरफलक और वर्गों की है। लेकिन मेरी राय में जेनेरिक रिपोजिटरी (के) में दूसरा सामान्य पैरामीटर अनावश्यक है। क्योंकि मुझे पता है कि MyEntity एक पहचान है, मुझे लगता है कि यह बहुत अच्छा होगा यदि मैं अंत में इस तरह उपयोग कर सकते हैं होगा:बेमानी सामान्य मापदंडों

public class MyService { 
    private GenericRepository<MyEntity> myEntityRepository; 
} 

लेकिन मैं सफल होने के बिना अलग अलग चीजें कोशिश कर रहा हूँ। क्या यह संभव है? यदि नहीं, तो क्यों नहीं?

अद्यतन: कुछ प्रतिक्रियाओं का उत्तर दें। मुझे लगता है कि कंपाइलर कुछ जानता है कि किस प्रकार मायनेटीटी में सामान्य है। उदाहरण के लिए:

public class MyEntityGenericRepository implements GenericRepository<MyEntity, Long> { 
    // compiles... 
} 

public class MyEntityGenericRepository implements GenericRepository<MyEntity, String> { 
    // compiler says: "Bound mismatch: The type MyEntity is not a valid substitute for the bounded parameter <T extends Identifiable<K>> of the type GenericRepository<T,K>" 
} 

उत्तर

7

मुझे नहीं लगता कि आप इसे छोड़ सकते हैं। T extends Identifiable<K> के साथ आप कहना चाहते हैं कि सामान्य प्रकार पैरामीटर Identifiable होना चाहिए। चूंकि Identifiable एक सामान्य वर्ग है, तो आपको इसके सामान्य प्रकार पैरामीटर का भी उल्लेख करना होगा (यदि आप नियमों के अनुसार खेलना चाहते हैं - यदि आप इसे छोड़ देते हैं, तो पिछड़े संगतता नियमों के कारण GenericRepository के लिए आप सभी सामान्य प्रकार की सुरक्षा खो देते हैं)। ध्यान दें कि K वास्तव में GenericRepository.get के पैरामीटर प्रकार के रूप में उपयोग किया जाता है। और चूंकि उस प्रकार T से भिन्न हो सकता है, इसलिए आपको इसे GenericRepository के अन्य सामान्य प्रकार पैरामीटर के रूप में घोषित करके कंपाइलर को संतुष्ट करने की आवश्यकता है। अन्यथा कंपाइलर को यह जानने का कोई तरीका नहीं है कि K क्या है।

+0

धन्यवाद हो सकता है अन्य कर सकते हैं, की तुलना में एक अंतरफलक है कि बस GenericRepository

public interface LongKeyedRepository<T extends Identifiable<Long>> extends GenericRepository<T, Long> { { //No new methods need to be defined } 

तब को परिष्कृत पेश करते हैं, लेकिन मैं सहमत नहीं हूँ । कृपया, मेरा संपादन देखें। – sinuhepop

+3

@sinuhepop, निश्चित रूप से संकलक यह जांच सकता है कि 'पहचानकर्ता ' में टाइप पैरामीटर के वास्तविक प्रकार के 'के' मैचों का मिलान किया गया है। फिर भी, आपको एक सामान्य प्रकार पैरामीटर होने के लिए * के * घोषित करने की आवश्यकता है (और इसके परिणामस्वरूप, तत्कालता के बिंदु पर अपना वास्तविक मान पास करें)। यह सिर्फ भाषा काम करता है। आप सही हैं कि इस ज्ञान * सिद्धांत में संकलक द्वारा अनुमानित किया जा सकता है, लेकिन यह अभी के लिए नहीं है, और कई सालों तक ... यदि कभी (दुर्भाग्यवश, जावा का विकास केवल उस दिशा में बहुत धीरे-धीरे चल रहा है। ..)। –

3

जेनेरिक रिपोजिटरी क्लास के दृष्टिकोण से यह अनावश्यक नहीं है। जब इसमें T get(K id) जैसे विधियां हैं, तो यह नहीं पता कि id तर्क किस प्रकार के अन्यथा स्वीकार कर सकता है। आप नीचे दिए गए लिख सकते हैं:

interface GenericRepository<T extends Identifiable<?>> { 
    T get(Object id); 
} 

अब आप Long एक प्रकार पैरामीटर के रूप में लिखने के लिए नहीं है, लेकिन आप अगर get विधि संकलन समय पर ठीक से प्रयोग किया जाता है संभावना की जांच करने के खो देते हैं। तो प्रकार परिवर्तनीय एक विशिष्ट उद्देश्य प्रदान करता है।

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

+0

कृपया मेरे संस्करण को देखें। ऐसा लगता है कि संकलक किसी भी प्रकार का अनुमान लगा सकता है। – sinuhepop

+0

@sinuhepop, नहीं, यह किसी भी प्रकार का उल्लंघन नहीं कर रहा है, केवल दो ठोस, परिभाषित प्रकार पैरामीटर की समानता की तुलना कर रहा है। (का एक सरल उदाहरण) टाइप अनुमान [यह] (http://docs.oracle.com/javase/tutorial/java/generics/gentypeinference.html) (जावा 7 में लागू) है। –

0

यदि मुझे गलत नहीं लगता है तो जेनेरिक सभी संकलित होंगे जैसे कि वे केवल Object थे। अब यह सुनिश्चित करने के लिए सिंटैक्स (हार्ड) चेक किया गया है कि आप सेब को संतरे से नहीं डाल रहे हैं क्योंकि जावा के प्रारंभिक डिज़ाइन के बाद जेनेरिक जोड़े गए थे। इस कारण है कि जेनरिक इतना विवश कर रहे हैं है ...

-1

क्यों आप से दूसरा कश्मीर नहीं निकाल सकते,

public interface GenericRepository<T extends Identifiable<K>, K> { 

तो बल्कि जैसा कि ऊपर यह की तुलना में, हम के रूप में

public interface GenericRepository<T extends Identifiable<K>> { 

से यह हो सकता है यह हम कर सकते हैं जो आप करना चाहते हैं।

+0

हां, लेकिन दुर्भाग्य से कंपाइलर कहता है "के को किसी प्रकार से हल नहीं किया जा सकता"। – sinuhepop

0

यह काम करेगा (यानी।संकलन)

public interface GenericRepository<T extends Identifiable> { 
    T get(T id); 
} 

लेकिन यह कहता है कि पहचानकर्ता एक कच्चा प्रकार है और इसे parametrized होना चाहिए।

उम्मीद है कि यह मदद करता है।

+0

यह बिल्कुल समान नहीं है - आपने 'के' के बजाय 'टी' प्रकार का तर्क लेने के रूप में' get' घोषित कर दिया है। तर्कसंगत रूप से यह सवाल का क्रूक्स है, कक्षा के भीतर 'के' संदर्भ कैसे बनाते समय इसे घोषित किए बिना संदर्भित किया जाए, इसलिए यह थोड़ा सा गड़बड़ाना है। :) –

+0

मैं कहूंगा कि निर्माण के दौरान इसे घोषित किए बिना वर्ग के भीतर के संदर्भ को संभव नहीं है। यह केवल एक चीज है जिसे मैं सोच सकता हूं सार्वजनिक इंटरफ़ेस जेनेरिक रिपोजिटरी <टी पहचान योग्य < ऑब्जेक्ट बढ़ाता है >> { टी प्राप्त करें (टी आईडी); } – aretai

+1

हाँ, यह सवाल है: "** क्या यह संभव है? यदि नहीं, तो क्यों नहीं? **" –

1

ज्यादा क्या आप

private LongKeyedRepository<MyEntity> myEntityRepository; 

आदि

+0

संकलित नहीं करेगा। वर्तमान में मैं इस तरह कुछ कर रहा हूं (मैंने अपनी संरचना को थोड़ा सा सरल बना दिया है)। लेकिन मुझे यह बहुत पसंद नहीं है, और मुझे समझ में नहीं आता क्यों जरूरत है। – sinuhepop

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