2010-01-13 3 views
14

, एक वस्तु, उस विधि और कुछ तर्क का समर्थन करता है वहाँ आपको लगता है कि गतिशील रूप से कॉल करने के लिए अनुमति देता है कि कुछ भाषा विशेषता है कि मान लें कि आप एक स्ट्रिंग के लिए एक विधि के नाम वाले है?क्या कोई स्कैला सुविधा है जो आपको एक विधि को कॉल करने की अनुमति देती है जिसका नाम स्ट्रिंग में संग्रहीत है?

तरह रूबी के send पैरामीटर के प्रकार।

उत्तर

25

आप जावा में प्रतिबिंब के साथ ऐसा कर सकते हैं:

class A { 
    def cat(s1: String, s2: String) = s1 + " " + s2 
} 
val a = new A 
val hi = "Hello" 
val all = "World" 
val method = a.getClass.getMethod("cat",hi.getClass,all.getClass) 
method.invoke(a,hi,all) 

और अगर आप चाहते हैं कि उसे स्काला में आसान आप एक वर्ग है कि आप के लिए यह करता है बना सकते हैं, के साथ साथ रूपांतरण के लिए एक अंतर्निहित होने के लिए:

case class Caller[T>:Null<:AnyRef](klass:T) { 
    def call(methodName:String,args:AnyRef*):AnyRef = { 
    def argtypes = args.map(_.getClass) 
    def method = klass.getClass.getMethod(methodName, argtypes: _*) 
    method.invoke(klass,args: _*) 
    } 
} 
implicit def anyref2callable[T>:Null<:AnyRef](klass:T):Caller[T] = new Caller(klass) 
a call ("cat","Hi","there") 

बात की इस तरह करने से क्रम त्रुटियों में संकलित समय त्रुटियों में कनवर्ट करता है, फिर भी (यानी यह अनिवार्य रूप से प्रकार प्रणाली में गतिरोध उत्पन्न), इसलिए सावधानी से उपयोग करें।

(संपादित करें:। और ऊपर के लिंक में NameTransformer का उपयोग देख - कहा कि मदद करेगा अगर आप ऑपरेटरों का उपयोग करने की कोशिश)

+0

मैं निम्नलिखित पर त्रुटि हो रही है 'सूची (1, 2) कॉल (" ले ", 1)' त्रुटि है 'प्रकार। बेमेल पाया:। इंट (1) की आवश्यकता: AnyRef नोट: एक अंतर्निहित से scala.Int => java.lang.Integer मौजूद है, लेकिन वस्तु से विरासत में मिली तरीकों अस्पष्ट गाया जाता है यह एक कंबल अंतर्निहित जो किसी भी स्केला बदल जाएगा से बचने के लिए है किसी भी AnyRef में। आप एक प्रकार के शिलालेख का उपयोग करना चाह सकते हैं: x: java.lang.Integer.' क्या आदिम प्रकारों को संभालने का कोई तरीका है? (मैं गतिशील रूप से तर्क सूची उत्पन्न करना चाहता हूं ... हो सकता है 'Any') – dips

+1

@dips - आप कर सकते हैं' .asInstanceOf [AnyRef] 'में (रास्ते पर' Any' साथ भी काम करता है), या '1: java.lang.Integer' त्रुटि पता चलता है के रूप में या आप पुरातन मिलान कर सकते हैं। और यदि आपको वास्तव में आवश्यकता है, तो केस-दर-मामले को संभालें, हालांकि आपको यहां आवश्यकता नहीं है। –

+0

धन्यवाद! तो मेरा 'कॉल' फ़ंक्शन हस्ताक्षर अब 'तर्क: कोई * * लेता है और मैं इसे' कॉल 'के शरीर में 'AnyRef *' में बदलता हूं,' args map {_.asInstanceOf [AnyRef]} '। उम्मीद है कि यह ठीक है। Subtleties, इसलिए पूछना नहीं जानते। – dips

6

हां। इसे प्रतिबिंब कहा जाता है। Here's a link to one way, using some experimental stuff हालांकि आपको याद रखना चाहिए कि स्कैला गतिशील भाषा नहीं है, और हो सकता है कि कुछ चीजें आसानी से करने में सक्षम न हों जो भाषाएं कर सकती हैं। आप शायद स्ट्रिंग पर एक मैच कर रहे हैं, और फिर सही विधि को कॉल कर रहे हैं।

+0

टूटी लिंक .... खेद :( –

0
scala> val commandExecutor = Map("cleanup" -> {()=> println("cleanup successfully")}) 
commandExecutor: scala.collection.immutable.Map[String,() => Unit] = Map(cleanup -> <function0>) 

scala> val command="cleanup" 
command: String = cleanup 

scala> commandExecutor(command).apply 
cleanup successfully 
1

हाँ आप कर सकते हैं! आपको विधि ऑब्जेक्ट की .invoke() विधि की आवश्यकता होगी। नीचे दिए गए सरल उदाहरण:।

case class MyCaseClass(i: String) { 
    def sayHi = { 
    println(i) 
    } 
} 
val hiObj = MyCaseClass("hi") 
val mtdName = "sayHi" 
// Method itself as an object 
val mtd = hiObj.getClass.getMethod(mtdName) 
mtd.invoke(hiObj) 
संबंधित मुद्दे

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