2011-02-02 18 views
5

का उपयोग कर स्कैला कन्स्ट्रक्टर का आविष्कार करने वाले तर्कों की गलत संख्या मैं स्कैला वर्ग (केस क्लास या सामान्य श्रेणी, दोनों प्रभावित) के निर्माता के newInstance विधि को आमंत्रित करने का प्रयास कर रहा हूं।प्रतिबिंब

हालांकि, मैं में संकेत संकेतों की गलत संख्या के साथ चल रहा हूं।

case class Vec2(x: Float, y: Float) 

object TestApp { 
    def main(args: Array[String]) { 
    //after some research I found the last constructor always to be the default 
    val ctor = classOf[Vec2].getConstructors.last 

    println("ctor = " + ctor) 
    println("takes parameters: " + ctor.getParameterTypes.length) 

    val params = new Array[Float](2) 

    params.update(0, 1.0f) 
    params.update(1, -1.0f) 

    println("num parameters: " + params.length) 

    println("trying to create new instance...") 
    try { 
     val x = ctor.newInstance(params) 
     println("new instance: " + x) 
    } 
    catch { 
     case ex => ex.printStackTrace 
    } 
    } 

उत्पादन इस प्रकार है::

ctor = public pd.test.Vec2(float,float) 
takes parameters: 2 
num parameters: 2 
trying to create new instance... 
java.lang.IllegalArgumentException: wrong number of arguments 
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) 
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39) 
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27) 
    at java.lang.reflect.Constructor.newInstance(Constructor.java:513) 
    at pd.test.TestApp$.main(TestApp.scala:60) 
    at pd.test.TestApp.main(TestApp.scala) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 
    at java.lang.reflect.Method.invoke(Method.java:597) 
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:115) 

मैं एक बार जावा में कुछ इस तरह का अनुभव किया है

निम्नलिखित पर विचार करें। उस स्थिति में जिस वर्ग को मैं तत्काल स्थापित करने की कोशिश कर रहा था वह एक और वर्ग की आंतरिक कक्षा थी, इसलिए जावा ने एक अनुमानित अतिरिक्त पैरामीटर की अपेक्षा की थी, जो कि संलग्न वर्ग (0 वर्ग को स्थैतिक घोषित किया गया था) की Class वस्तु थी, या एक उदाहरण संलग्न वर्ग।

हालांकि, इस मामले में, Vec2 का कोई संलग्नित क्लास है, जब तक स्काला एक आंतरिक रूप से कहते हैं (हालांकि, java.lang.Class.getEnclosingClass() रिटर्न मेरे लिए null)।

तो मेरा सवाल है कि प्रतिबिंब का उपयोग करके स्कैला कक्षाओं को तुरंत कैसे चालू किया जाए? क्या कोई अतिरिक्त पैरामीटर स्केल कन्स्ट्रक्टर अपेक्षाकृत अपेक्षा करते हैं?

उत्तर

11

newInstance विधि एक varargs पैरामीटर लेता है। स्कैला (जावा के विपरीत) में, आप केवल एक सरणी पास नहीं कर सकते हैं और इसे स्वचालित रूप से सभी तर्कों के रूप में माना जाता है। यदि यह तुम क्या चाहते हो आप इस तरह स्पष्ट रूप से इसे करने की जरूरत है:

ctor.newInstance(params:_*) 

क्या आप इस समय कर रहे हैं निर्माता के लिए सबसे पहले तर्क के रूप में 2 तत्वों के साथ एक सरणी से गुजर रहा है।

+1

'newInstance' 'java.lang.Object' उप प्रकार के तर्कों को छोड़ देता है, तो आपको' ctor.newInstance (params.map (_। AsInstanceOf [ऑब्जेक्ट]): _ *)' ' फ्लोट ' –

+0

धन्यवाद, इससे मदद मिली! वसील भी धन्यवाद। मैं उस जेनेरिक क्लास के साथ उस समस्या में भाग नहीं पाया जिस पर मैं काम कर रहा हूं, जो एक ऐरे [AnyRef] बनाता है। मैंने जो उदाहरण पोस्ट किया वह एक सरलीकृत संस्करण था। :) – pdinklag

+0

@ वासिल जावा के साथ, स्कैला किसी अंतर्निहित आदिम प्रकार के ऑटोबॉक्स को ऑटोबॉक्स कर देगा, इसलिए स्कैला 'फ्लोट 'या तो' फ्लोट 'या' जावा.लांग.फ्लैट 'हो सकता है। चूंकि स्कैला varargs 'Seq' और Seq का उपयोग एक मिटा प्रकार है, तो आप निश्चित हो सकते हैं कि आप जो भी पारित कर रहे हैं उसे पहले से ही बॉक्स किया जाएगा और' ऑब्जेक्ट ' –