जावा जेनरिक अभिव्यक्ति के प्रकार के आधार पर जेनेरिक प्रकार पैरामीटर के प्रकार का अनुमान लगा सकता है। पर विचार करें निम्नलिखित:स्कैला और जावा जेनिक्स - नेस्टेड प्रकारों को निकालने और वापस करने के लिए
public static <T> T uncheckedCast(Object o) {
return (T)o;
}
हम इसे इस तरह के रूप कॉल कर सकते हैं:
Map<Baz,Bog> bazbogMap = new HashMap<Baz,Bog>();
String foo = uncheckedCast(bazbogMap);
यह संकलन लेकिन एक RuntimeException
फेंक जब यह शुरू हो जाती है, क्योंकि यह एक String
को Map
कास्ट करने के लिए कोशिश करेंगे लेकिन असफल । लेकिन मुद्दा यह है कि जावा ने <T>
के मूल्य को कॉलसाइट पर अपेक्षित परिणामी प्रकार के आधार पर अनुमानित किया।
हम भी साथ स्काला में ऐसा कर सकते हैं: अब तक
def uncheckedCast[T](o: AnyRef): T = o.asInstanceOf[T]
, तो अच्छा।
जावा भी नेस्टेड परिभाषाओं से प्रकार तर्क प्राप्त करेगा और उन (यानी हम वास्तव में उपयोग करने से पहले के रूप में ऊपर के लिए इसका इस्तेमाल करने के लिए एक प्रकार के परिणाम आवंटित करने के लिए नहीं है।; जावा जानता है क्या यह पहले से ही है) लौट सकते हैं
एक साधारण इस दिखा वर्ग:
import java.util.HashMap;
import java.util.Map;
public class KeysAndValues {
public interface Key<T> {}
public static class StringKey implements Key<String> {}
private final Map<Class<?>, Object> lookup;
public KeysAndValues() {
lookup = new HashMap<Class<?>, Object>();
}
@SuppressWarnings("unchecked")
public <V, K extends Key<V>> V put(Class<K> key, V value) {
return (V) lookup.put(key, value);
}
@SuppressWarnings("unchecked")
public <V, K extends Key<V>> V get(Class<K> key) {
return (V) lookup.get(key);
}
public static void test() {
KeysAndValues kv = new KeysAndValues();
kv.put(StringKey.class, "BAM!"); // returns null
kv.put(StringKey.class, "BOOM!"); // returns "BAM!"
kv.get(StringKey.class); // returns "BOOM!"
}
}
हालांकि, स्काला में इस वर्ग समस्याओं का कारण बनता। आरईपीएल: के रूप में V
पैरामीटर की जरूरत है
scala> val kv = new KeysAndValues
kv: KeysAndValues = [email protected]
scala> import KeysAndValues.StringKey
import KeysAndValues.StringKey
scala> kv.put(classOf[StringKey], "BAM!")
res0: java.lang.String = null
scala> kv.put(classOf[StringKey], "BOOM!")
res1: java.lang.String = BAM!
scala> kv.get(classOf[StringKey])
<console>:10: error: inferred type arguments [Nothing,KeysAndValues.StringKey] do not conform to method get's type parameter bounds [V,K <: KeysAndValues.Key[V]]
kv.get(classOf[StringKey])
put()
करने के लिए दो कॉल V
प्रकार पैरामीटर है जो उन्हें काम करने के लिए अनुमति देता है के लिए एक मूल्य निर्दिष्ट करते हैं, लेकिन जैसे ही K
पैरामीटर की विरासत से निकाला जाता था, चीजों को तोड़ने नीचे। जावा कोड में ऐसा कोई मुद्दा नहीं है।
एक ही रास्ता स्काला प्राप्त करने के लिए शिकायत करने के लिए नहीं स्पष्ट रूप से परिभाषित करने के लिए प्रकार है:
kv.get[String, StringKey](classOf[StringKey])
(कुछ सरल के लिए और की तरह काल्पनिक ऊपर यह मामूली बात नहीं (सूखी उल्लंघन करता है), लेकिन और अधिक शामिल कुछ के लिए, स्टैनफोर्ड कोर NLP एपीआई, आप की तरह कुछ करने के लिए जहां की तरह:
doc.get[java.util.Map[Integer, CorefChain], CorefChainAnnotation](classOf[CorefChainAnnotation])
कौन सा मैन्युअल ताकि आप उन्हें जोड़ सकते हैं नेस्टेड प्रकार को देख भी शामिल है, काफी दर्द है)
।प्रश्न (ओं):
क्या टाइप पैरामीटर को बिना किसी शब्द के निर्दिष्ट किए बिना काम करने के लिए कोई तरीका है? सबसे महत्वपूर्ण बात यह है कि यह किस समस्या से शुरू हो रहा है? जावा स्केल नहीं होने पर टाइप तर्क का अनुमान लगाने में सक्षम कैसे है?
संपादित करें 1: कोड स्टैनफोर्ड कोर NLP समस्या का प्रदर्शन का सबसे निकाला गया और स्काला/जावा जेनरिक कि इस मुद्दे को एक मिसाल है में अंतर का एक सामान्य उदाहरण के साथ यह बदल दिया।
क्या आप बाहरी पुस्तकालयों के बिना संकलित सादे जावा और स्कैला कोड में अपनी समस्या का पुनरुत्पादन कर सकते हैं? –
शायद। मुझे उस पर एक दरार लेने दो। –
अंतर दिखाने वाला जावा क्लास और आरईपीएल आउटपुट जोड़ा गया। –