2012-03-18 17 views
5

संभव डुप्लिकेट:
Is List<Dog> a subclass of List<Animal>? Why aren't Java's generics implicitly polymorphic?
Java Generics — Assigning a list of subclass to a list of superclassकच्चे प्रकार और जेनेरिक्स - जावा

कच्चे प्रकार के साथ आप आसानी से कुछ इस तरह कह सकते हैं।

[...] // MyClass is generic with upper bound of Object 

MyClass c = new MyClass<Double>(); 

[...] 

लेकिन इस

MyClass<Number> c = new MyClass<Double>() 

मुझे समझ नहीं आता क्यों है अनुमति नहीं है। मेरी किताब मुझे, क्यों दूसरा काम नहीं करता है बताता है, क्योंकि आप एक MyClass<Double> करने के लिए एक पूर्णांक नहीं जोड़ सकते। क्या यह बताते नहीं है क्यों MyClass<Double>, MyClass<Object> का एक उपवर्ग (या समतुल्य कच्चे प्रकार फार्म) है उसके बाद से दो वस्तु के उपवर्ग है।

तो क्यों पहले अनुमति दी है, तो दूसरा रूप नहीं है। कृपया महसूस करें कि मैं इसके लिए नया हूं।

संपादित करें: ले रहा है यह एक कदम आगे पहले उदाहरण में क्या होगा यदि संख्या ऊपरी बाध्य किया गया था?

आप यहाँ प्रकार विलोपन के प्रभाव

class Untitled { 
public static void main(String[] args) { 

} 
public static<T> void c(T t) 
{ 
    t.SubClassMethod();// this won't work because class Object has no such method. But if I change the upperbound to SubClass it will. 
      t.toString() // this will because class Object has such a method 
} 
} 

मेरे बिंदु कारण है कि यह कोई फर्क होना चाहिए कि क्या के रूप में अगर यह अंततः ऊपरी वैसे भी बाध्य के रूप में इलाज हो जाता है सामान्य घोषित किया जाता है है देख सकते हैं?

+0

मेरा प्रश्न विपरीत है, मैं पूछ रहा हूं कि आप उप-वर्ग – rubixibuc

+0

से कच्चे प्रकार को क्यों असाइन कर सकते हैं, इस प्रश्न के लिए आधार गलत है, क्योंकि टाइप एरर की वजह से केवल चिंता ही है कि ऊपरी बाउंड के साथ काम करता है विधि, और कास्टिंग के लिए जांचने के लिए प्रकार का उपयोग करता है। कम से कम यही मैंने पढ़ा है – rubixibuc

उत्तर

3

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

कच्चे प्रकार के व्यवहार के तरीके और पैरामीटरेटेड प्रकार के तरीके के बीच की तुलना कुछ मूलभूत रूप से नकली तरीके से होती है। डिजाइन का इरादा यह नहीं है कि कच्चे प्रकार को पैरामीटर घोषित करने के लिए 'वैकल्पिक' माना जाता है। रॉ कोड का उपयोग करने वाला नया कोड गलत कोड है। इसे संकलित करना कानूनी है ताकि पुराने कोड अभी भी काम कर सकें।

मेरा मुद्दा यह है कि जेनेरिक को के रूप में घोषित क्यों किया जाना चाहिए यदि इसे आखिरकार ऊपरी सीमा के रूप में माना जाता है?

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

+0

मैं कुछ गहन शोध करने के बाद अपने स्वयं के प्रश्न के उत्तर के बारे में था और आपने इसे पूरी तरह उत्तर दिया। हां यह समझ में आता है, अगर वापसी का प्रकार सहमत नहीं होता तो क्या होगा। इसे स्पष्ट करने के लिए धन्यवाद। – rubixibuc

+0

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

+0

हां, यही वह है जो मैं अपने रन-ऑन वाक्य में कहने की कोशिश कर रहा था कि मैं कुछ हद तक खराब हो गया :) – Affe

3

मान लीजिए कि MyClass इस तरह है:

public class MyClass<T>{ 
    T value; 

    public void foo(T arg){ 
    value = arg; 
    } 
} 

और फिर उन दो अन्य वर्गों:

class A{ } 

class B extends A { } 
अब

कल्पना कीजिए कि अगर आप ऐसा करेंगे होता है:

MyClass<A> container = new MyClass<B>(); 
container.foo(new A()); 

आप ' डी को बी के प्रकार के क्षेत्र में डालने का प्रयास करें। आप जिस प्रतिबंध का सामना कर रहे हैं वह इस तरह के थाई को रोकने के लिए सोचा जाता है ngs। सी # में और बाहर जेनरिक के लिए मानकों के संदर्भ में एक गंधा समाधान ...

+1

'नया टी [2]' ?! ओह ओह, कंपाइलर त्रुटि! – Jeffrey

+1

@ जेफरी यदि आप मानते हैं कि एक भाग/करता/संकलित करता है, तो यह उत्तर समानता से समस्या को बहुत ही स्पष्ट रूप से दिखाता है। – millimoose

+0

हां, मुझे वह हिस्सा मिल गया है, जो मुझे समझ में नहीं आता है, पहला कारण त्रुटि के बिना संकलित करता है – rubixibuc

4

है इस प्रयास करें:

MyClass<? extends Number> c = new MyClass<Double>(); 
1

किसी भी MyClass<XXX> एक MyClass है, लेकिन आप क्या कह रहे हैं के विपरीत, MyClass<Double> नहीं है MyClass<Object> का उप-वर्ग।

यदि आप विलोपन के लिए खोज, here की तरह इसके बारे में अधिक जानकारी प्राप्त कर सकते हैं।

+0

कच्चे प्रकार का प्रकार सिर्फ प्रकार के प्रकार के साथ नहीं है? शायद मैं इसे गलत समझ रहा हूँ? – rubixibuc

+0

तब कच्चे प्रकार का क्या है? – rubixibuc

+0

मैंने जो कहा और ओरेकल की वेबसाइट पर प्रलेखन पढ़ा। यदि ऊपरी बाउंड ऑब्जेक्ट MyClass = MyClass नहीं है? – rubixibuc

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