2010-04-17 14 views
10

निम्नलिखित कोड पर विचार करें:कैसे (स्काला 2.8) प्रतिबिंब के माध्यम से एक फ़ील्ड का मान का उपयोग करने के

class Foo(var name: String = "bar") 

अब मैं मूल्य प्राप्त करने के लिए प्रयास करें और प्रतिबिंब के माध्यम से इसके बारे में सही प्रकार:

val foo = new Foo 
val field = foo.getClass.getDeclaredField("name") 
field.setAccessible(true) 
//This is where it doesn't work 
val value = field.get(????) 

मैंने field.get (foo) जैसी चीजों की कोशिश की, लेकिन यह सिर्फ एक java.lang.Object लौटाता है लेकिन कोई स्ट्रिंग नहीं। असल में मुझे सही प्रकार की आवश्यकता है, क्योंकि मैं इस पर एक विधि का आह्वान करना चाहता हूं (ई जी। ToCharArray)।

ऐसा करने का सुझाव दिया गया तरीका क्या है?

उत्तर

0

ऐसा लगता है कि कि सभी संभव कोशिश कर बाहर के साथ मैं क्या चाहते हो पाना संभव नहीं है हाथ ई द्वारा प्रकार। जी।

o match { 
    case I if o.isInstanceOf[Int] => val i = I.asInstanceOf[Int] 
    case F if o.isInstanceOf[Float] => val f = I.asInstanceOf[Float] 
    case S if o.isInstanceOf[String] => val s = I.asInstanceOf[String] 
    case OF if o.getGenericType.toString == "scala.Option<java.lang.Float>" => val of = OF.asInstanceOf[Option[Float]] 
    . 
    . 
    . 

ठीक है, चलो भविष्य जहां कुछ इस तरह काम करता है में एक भाषा नहीं होगा आशा है कि ...

3

getDeclaredFieldjava.lang.Class का एक तरीका है।

फ़ील्ड प्राप्त करने के लिए आपको foo.getDeclaredField("name")foo.getClass.getDeclaredField("name") (या classOf[Foo].getDeclaredField("name")) को बदलना होगा।

आप getType विधि Field में विधि प्राप्त कर सकते हैं लेकिन यह आपकी मदद नहीं करेगा क्योंकि यह Class[_] देता है। आपको यह देखते हुए कि यह प्रकार एक स्ट्रिंग है, आप field.get(foo).asInstanceOf[String]

+0

मैंने लापता getClass तय किया, यह केवल एक निरीक्षण था। मुझे आश्चर्य है कि बिना किसी चीज के यह जानने के बिना कलाकार कैसे किया जाए। अगर मुझे कक्षा के बारे में सब कुछ पता था तो मुझे संभालना होगा मुझे प्रतिबिंब की आवश्यकता नहीं होगी ... सुझावों के लिए धन्यवाद! – soc

+0

आप वस्तु को मिलान कर सकते हैं जैसे कि 'वैल्यू मैच {केस एस: स्ट्रिंग =>/* स्ट्रिंग के साथ कुछ करें */case _ =>/* कुछ और करें * /} '। पता नहीं है कि मैं समझता हूं कि आप क्या करना चाहते हैं। – gerferra

1

AFAIK का उपयोग करके लौटाए गए मान को हमेशा कास्ट कर सकते हैं, प्रतिबिंब हमेशा ऑब्जेक्ट के साथ काम करता है, और आपको खुद को परिणाम डालना पड़ता है।

+0

हां, मैंने इस सवाल को गलत समझा था, अब मैंने मील जवाब बदल दिया है। – gerferra

5

जैसा कि अन्य ने उल्लेख किया है, प्रतिबिंब विधियां Object लौटाती हैं ताकि आपको कास्ट करना पड़े। आप उस विधि का बेहतर उपयोग कर सकते हैं जो स्कैला कंपाइलर निजी क्षेत्र की दृश्यता को बदलने के बजाय क्षेत्र पहुंच के लिए बनाता है। (मैं भी नहीं यकीन है कि अगर नाम निजी क्षेत्र एक्सेसर तरीकों के समान होने की गारंटी है कर रहा हूँ।)

val foo = new Foo 
val method = foo.getClass.getDeclaredMethod("name") 
val value = method.get(foo).asInstanceOf[String] 
+0

** foo.getClass.getDeclaredField ("name") के साथ अच्छी तरह से काम कर रहा है ** क्योंकि foo.getClass.getDeclaredMethod में * get * नामक सदस्य नहीं है – Kruser

0

यह एक fieldnames की सूची और एक मामले वर्ग के अपने मूल्य कैसे प्राप्त कर सकते हैं:
सबसे पहले, प्रतिबिंब का उपयोग करके, फ़ील्ड जानकारी निम्नानुसार प्राप्त करें -

val TUPLE2_OF_FIELDNAME_TO_GETTERS = typeOf[<CLASS>].members 
.filter(!_.isMethod) 
.map(x => (x.name.toString, classOf[<CLASS>].getDeclaredMethod(x.name.toString.trim))) 

इसका उपयोग कैसे करें?

getFieldNameAndValue(obj: <CLASS>): Seq[(String, String)] { 
    var output = Seq[(String, String)]() 
for(fieldToGetter <- TUPLE2_OF_FIELDNAME_TO_GETTERS) { 
     val fieldNameAsString = fieldToGetter._1 
     val getter = fieldToGetter._2 
     val fieldValue = getter.invoke(obj).toString 
     output += (fieldName, fieldValue) 
    } 
} 
संबंधित मुद्दे