(scala -unchecked
) पर अनियंत्रित चेतावनी के साथ स्काला दुभाषिया में इस उदाहरण चल रहा है निम्न चेतावनी का उत्पादन: warning: refinement AnyRef{def doesNotExist(Int,List[_]): Double} in type pattern is unchecked since it is eliminated by erasure
। दुर्भाग्यवश, इस तरह के एक सामान्य प्रकार को रनटाइम पर चेक नहीं किया जा सकता क्योंकि JVM ने जेनिक्स को संशोधित नहीं किया है।
सभी कि JVM इस पैटर्न मैच में देखता है:
"hello" match {
case s: Object => ...
case annon: Object => ...
}
संपादित करें: अपनी टिप्पणी के जवाब में, मैं एक समाधान के बारे में सोच कर दिया गया है, लेकिन समय यह कल पोस्ट करने के लिए नहीं था । दुर्भाग्यवश, भले ही कार्य करना चाहिए, संकलक उचित Manifest
को इंजेक्ट करने में विफल रहता है।
जिस समस्या को आप हल करना चाहते हैं वह तुलना करना है यदि कोई ऑब्जेक्ट किसी दिए गए संरचनात्मक प्रकार का है। यहाँ (, स्काला 2.8-r20019 के रूप में स्काला 2.7.6.final मुझ पर एक दो बार दुर्घटनाग्रस्त हो गया इसी तरह के विचारों के साथ खेलते हुए) कुछ कोड मैं के बारे में सोच कर दिया गया है
type Foo = AnyRef { def doesNotExist(i: Int, x: List[_]): Double }
def getManifest[T](implicit m: Manifest[T]) = m
def isFoo[T](x: T)(implicit mt: Manifest[T]) =
mt == getManifest[Foo]
विधि isFoo
मूल रूप से प्रकट होता है तुलना Foo
की कक्षा x
। एक आदर्श दुनिया में, संरचनात्मक प्रकार का प्रकटन आवश्यक विधियों वाले किसी भी प्रकार के प्रकट होने के बराबर होना चाहिए। कम से कम यह मेरी सोच की ट्रेन है। दुर्भाग्यवश यह संकलित करने में विफल रहता है, क्योंकि संकलक के बजाय Manifest[AnyRef]
को getManifest[Foo]
पर कॉल करते समय इंजेक्ट करता है। दिलचस्प बात यह है कि यदि आप संरचनात्मक प्रकार का उपयोग नहीं करते हैं (उदाहरण के लिए, type Foo = String
), यह कोड संकलित और अपेक्षा के अनुसार काम करता है। मैं किसी बिंदु पर एक प्रश्न पोस्ट करूंगा कि यह संरचनात्मक प्रकारों के साथ क्यों विफल रहता है - क्या यह एक डिज़ाइन निर्णय है, या यह केवल प्रयोगात्मक प्रतिबिंब API की समस्या है।
विफल होने पर, आप जावा प्रतिबिंब का उपयोग यह देखने के लिए कर सकते हैं कि किसी ऑब्जेक्ट में कोई विधि है या नहीं।
def containsMethod(x: AnyRef, name: String, params: java.lang.Class[_]*) = {
try {
x.getClass.getMethod(name, params: _*)
true
}
catch {
case _ => false
}
}
जो काम करता है के रूप में उम्मीद:
containsMethod("foo", "concat", classOf[String]) // true
containsMethod("foo", "bar", classOf[List[Int]]) // false
... लेकिन यह बहुत अच्छा नहीं है।
इसके अलावा, ध्यान दें कि संरचनात्मक प्रकार की संरचना रनटाइम पर उपलब्ध नहीं है। यदि आपके पास def foo(x: {def foo: Int}) = x.foo
विधि है, तो मिटाने के बाद आपको def foo(x: Object) = [some reflection invoking foo on x]
मिलती है, प्रकार की जानकारी खो जाती है। यही कारण है कि प्रतिबिंब का उपयोग पहली जगह में किया जाता है, क्योंकि आपको Object
पर एक विधि का आह्वान करना पड़ता है और JVM को यह नहीं पता कि Object
में यह तरीका है या नहीं।
मैं अपनी टिप्पणी :) के प्रकाश में मेरा उत्तर का विस्तार किया है। –