2011-03-18 22 views
22

मेरे पास एक सारणी वर्ग है जिसमें एक सामान्य विधि है और मैं जेनेरिक पैरामीटर के लिए विशिष्ट प्रकारों को प्रतिस्थापित करके जेनेरिक विधि को ओवरराइड करना चाहता हूं। तो छद्म कोड में मेरे पास निम्न है:जावा जेनेरिक विधि विरासत और ओवरराइड नियम

public abstract class GetAndParse { 
    public SomeClass var; 

    public abstract <T extends AnotherClass> void getAndParse(T... args); 
} 

public class Implementor extends GetAndParse { 
    // some field declarations 

    // some method declarations 

    @Override 
    public <SpecificClass> void getAndParse(SpecificClass... args) { 
    // method body making use of args 
    } 
} 

लेकिन किसी कारण से मुझे ऐसा करने की अनुमति नहीं है? क्या मैं किसी प्रकार की वाक्यविन्यास त्रुटि कर रहा हूं या इस तरह की विरासत और ओवरराइडिंग की अनुमति नहीं है? विशेष रूप से मुझे @Override के बारे में त्रुटि मिल रही है क्योंकि ग्रहण आईडीई मुझे getAndParse लागू करने के लिए याद दिलाता रहता है।

यहां बताया गया है कि मैं उपरोक्त कोड को कैसे काम करना चाहता हूं। मेरे कोड में कहीं और एक ऐसी विधि है जो GetAndParse को लागू करने वाली वस्तुओं के उदाहरणों की अपेक्षा करती है, जिसका विशेष रूप से अर्थ है कि उनके पास getAndParse विधि है जिसका मैं उपयोग कर सकता हूं। जब मैं उस उदाहरण पर getAndParse पर कॉल करता हूं तो संकलक यह देखने के लिए जांच करता है कि मैंने उचित तरीके से T के विशिष्ट उदाहरणों का उपयोग किया है, इसलिए विशेष रूप से TAnotherClass का विस्तार करना चाहिए और यह SpecificClass होना चाहिए।

+0

छद्म कोड बहुत सार, अधिक जानकारी की आवश्यकता है – irreputable

+0

'सार्वजनिक सार <टी का उपयोग करके अन्य क्लास> शून्य प्राप्त करें और पार्स (Args ... args); 'कोई समझ नहीं आता है। किस प्रकार के पैरामीटर के लिए अच्छा है? कंपाइलर को अपना वास्तविक मूल्य कैसे निर्धारित करना चाहिए और इसे कहां उपयोग करना चाहिए? – maaartinus

+0

क्या आप हमें एक पूरा उदाहरण प्राप्त कर सकते हैं, जो वास्तव में संकलित (समस्याग्रस्त त्रुटि के अलावा) है और आपके द्वारा उल्लिखित त्रुटि उत्पन्न करता है? –

उत्तर

23

हम यहां क्या कर रहे हैं अलग-अलग प्रकार के पैरामीटर प्रत्येक के साथ दो अलग-अलग तरीके हैं।

public abstract <T extends AnotherClass> void getAndParse(Args... args); 

यह टी नाम के एक प्रकार पैरामीटर के साथ एक तरीका है, और AnotherClass से घिरा है, जिसका अर्थ AnotherClass से प्रत्येक उप-प्रकार एक प्रकार पैरामीटर के रूप में अनुमति दी है।

public <SpecificClass> void getAndParse(Args... args) 

यह SpecificClass नाम के एक प्रकार पैरामीटर, Object से घिरा (प्रत्येक प्रकार के अर्थ एक प्रकार पैरामीटर के रूप में अनुमति दी है) के साथ एक विधि है। क्या आप वास्तव में यह चाहते हैं?

क्या Args के अंदर उपयोग किया गया प्रकार पैरामीटर है? मुझे लगता है कि समस्या वहां होगी।


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

public abstract <T extends AnotherClass> void getAndParse(T... args); 

का अर्थ है कि विधि का फोन करने वाले साथ वह विधि कॉल करना चाहता है जो प्रकार पैरामीटर तय कर सकते हैं, जब तक यह है के रूप में है AnotherClass के कुछ उप प्रकार। इसका मतलब यह है कि प्रभाव में AnotherClass प्रकार की किसी भी वस्तु के साथ विधि को बुलाया जा सकता है।

चूंकि कॉलर टाइप पैरामीटर का निर्णय ले सकता है, इसलिए आप पैरामीटर प्रकार को SpecificClass पर संकुचित कर सकते हैं - यह विधि का कार्यान्वयन नहीं होगा, लेकिन एक ही नाम (ओवरलोडिंग) के साथ एक और तरीका होगा।

public abstract class GetAndParse<T extends AnotherClass> { 
    public SomeClass var; 

    public abstract void getAndParse(T... args); 
} 

public class Implementor extends GetAndParse<SpecificClass> { 
    // some field declarations 

    // some method declarations 

    @Override 
    public void getAndParse(SpecificClass... args) { 
    // method body making use of args 
    } 
} 

अब getAndParse विधि माता पिता वर्ग 'विधि लागू करता है:

शायद तुम कुछ इस तरह करना चाहते हैं।

+3

मुझे एक प्रकार पैरामीटर नहीं चाहिए। मैं संकलक को जांचना चाहता हूं और सुनिश्चित करना चाहता हूं कि 'विशिष्ट क्लास' 'अन्य क्लास 'का विस्तार है। – davidk01

1

नहीं, यह मान्य नहीं है। क्या होगा यदि GetAndParse संदर्भ वाले किसी व्यक्ति ने इसे पर क्लास AnotherClass विस्तारित किया है?

+0

मुझे समझ में नहीं आता कि यह एक समस्या क्यों है।मेरे पास एक कार्यान्वयनकर्ता है जो 'GetAndParse' बढ़ाता है और' T' के प्रकार को 'SpecficClass' में ठीक करता है, जिसे संकलक जांचने के लिए सुनिश्चित करता है कि मेरे कोड में' अन्य क्लास 'को तब तक विस्तारित किया जाए जब मेरे पास' कार्यान्वयनकर्ता 'का उदाहरण हो और' getAndParse ' एक प्रकार के साथ जो 'विशिष्ट क्लास' से मेल नहीं खाता है, मुझे एक त्रुटि मिलनी चाहिए। – davidk01

+0

@ davidk01: GetAndParse द्वारा प्रदान किया गया अनुबंध कहता है कि इसे लागू करने वाले प्रत्येक व्यक्ति को किसी अन्य प्रकार के विस्तार के लिए ऐसा करना चाहिए। 'GetAndParse foo = new Implementor();' आपको किसी अन्य क्लास के किसी भी एक्सटेंशन के लिए 'foo.getAndParse'' कॉल करने में सक्षम होना चाहिए - यदि संकलक ने इसे लागू नहीं किया है, तो आप ऑब्जेक्ट का उपयोग भी कर सकते हैं, जेनरिक का बिंदु है संकलन-समय प्रकार की सुरक्षा सुनिश्चित करें – Erik

1

यह बकवास हो जाता है जब किसी के पास GetAndParse टाइप करने का संदर्भ होता है और getAndParse विधि को कॉल करने का प्रयास करता है। अगर बिल्ली और कुत्ता एक और क्लास का विस्तार करते हैं। मुझे उम्मीद है कि GetAndParse # get andParse को बिल्ली या कुत्ते के साथ कॉल करने में सक्षम होना चाहिए। लेकिन कार्यान्वयन ने इसे प्रतिबंधित करने और इसे कम संगत बनाने की कोशिश की है!

+0

यही कारण है कि आप जो करना चाहते हैं वह असंभव है, अगर मैं इसे पसंद नहीं करता हूं तो मैं क्षमा चाहता हूं। संकलन समय जेनेरिक आपके लिए इसे लागू करने में सक्षम नहीं हैं। कंपाइलर को यह जानने के लिए कैसे किया जाता है कि रनटाइम पर सबक्लास क्या होगा? यह पूरी तरह से संभव है कि कार्यान्वयन कारखाने के इंटरफ़ेस द्वारा वापस कर दिया गया हो और एक अलग पुस्तकालय से आता है जिसे आप संकलित भी नहीं कर रहे हैं! संकलन समय पर सुरक्षा के लिए टाइप पैरामीटर को संक्षिप्त करने की जांच नहीं की जा सकती है। – Affe

8

जावा जेनरिक में "एरर" नामक अवधारणा के कारण आप इस समस्या को देख रहे हैं। पिछली संगतता का समर्थन करने के लिए जावा "मिटा" का उपयोग करता है। यानी जावा कोड जो जेनेरिक का उपयोग नहीं करता था।

मिटाना प्रक्रिया:
संकलक पहले एक प्रकार की जाँच करेंगे और फिर इसे (मिटाएं) निकाल देंगे सभी प्रकार जितना संभव हो उतना मानकों, और भी Typecasting डालने जहां कभी आवश्यक।

उदाहरण:

public abstract <T extends AnotherClass> void getAndParse(T paramAnotherClass); 

बन जाएगा

public abstract void getAndParse(AnotherClass paramAnotherClass); 

वर्ग "Implementor.java" में,

कोड

public <SpecificClass> void getAndParse(T paramAnotherClass) 

बन जाएगा
public void getAndParse(SpecificClass paramAnotherClass){ } 

संकलक देखेंगे कि आपने अमूर्त विधि को सही ढंग से लागू नहीं किया है। सार विधि और लागू विधि के बीच एक प्रकार का मेल नहीं है। यही कारण है कि आप त्रुटि देख रहे हैं।

अधिक जानकारी यहां मिल सकती है। http://today.java.net/pub/a/today/2003/12/02/explorations.html

1

आप कर सकते हैं नहीं ओवरराइड विशिष्ट प्रकार टी क्योंकि वहाँ (बाईटकोड स्तर पर यदि आप चाहें) वास्तव में प्रकार विलोपन (अन्य उत्तर देखें) की वजह से केवल एक ही विधि getAndParse:

public abstract void getAndParse(AnotherClass... args); // (1) 

हर के लिए टी का प्रकार, एक ही विधि का उपयोग किया जाता है।

आप अधिभार यह (मुझे लगता है कि) कर सकते हैं:

लेकिन इस से एक भिन्न तरीके से नहीं होगा (1) चींटी यह नहीं सामान्य कोड से बुलाया जाएगा:

T x = whatever; 
    object.getAndParse(x); // Calls (1) even if T is derived from SpecificClass 
संबंधित मुद्दे