2009-12-16 16 views
22

में स्ट्रिंग नाम द्वारा ऑब्जेक्ट इंस्टेंस प्राप्त करना मुझे स्ट्रिंग नाम द्वारा परिभाषित ऑब्जेक्ट (या "सिंगलटन ऑब्जेक्ट" या "साथी ऑब्जेक्ट" ... वर्ग के अलावा कुछ भी चाहिए) की आवश्यकता है। दूसरे शब्दों में, अगर मैं में:स्केल

GetSingletonObjectByName("myPackage.myObject") match { 
    case instance: myPackage.myObject => "instance is what I wanted" 
} 

उत्तर

12

स्काला अभी भी एक प्रतिबिंब एपीआई याद आ रही है:

package myPackage 
object myObject 

... फिर वहाँ इस तरह कुछ भी नहीं है।

import scala.reflect.Manifest 
def companionObj[T](implicit man: Manifest[T]) = { 
    val c = Class.forName(man.erasure.getName + "$") 
    c.getField("MODULE$").get(c) 
} 


scala> companionObj[List[Int]].asInstanceOf[List$].make(3, "s") 
res0: List[Any] = List(s, s, s) 

इस तरह स्केला पर निर्भर करता है:

import scala.reflect._ 
def companion[T](implicit man: Manifest[T]) : T = 
    man.erasure.getField("MODULE$").get(man.erasure).asInstanceOf[T] 


scala> companion[List$].make(3, "s") 
res0: List[Any] = List(s, s, s) 

untyped साथी आप जिस ऑब्जेक्ट वर्ग सीधे उपयोग कर सकते हैं प्राप्त करने के लिए: आप साथी वस्तु वर्ग लोड करके साथी वस्तु का एक उदाहरण प्राप्त कर सकते हैं जावा कक्षाओं में मैप किया गया है।

+1

पवित्र गाय की तरह कर सकते हैं। क्या आप जानते हैं कि यह वाक्यविन्यास स्कैला स्पेक का एक निश्चित हिस्सा है (जैसा कि भाषा में किसी और चीज के रूप में तय किया गया है)? ऐसा लगता है कि इस पर भरोसा करना एक बुरा विचार है। और चूंकि मेरा लक्ष्य कोड * स्पष्ट * बनाना था ... धन्यवाद! – Dave

+0

जैसा कि उन्होंने उल्लेख किया है, अभी तक स्कैला में कोई प्रतिबिंब एपीआई नहीं है, इसलिए क्या यह स्कैला स्पेक द्वारा कवर किया गया है या नहीं, यह आपके लिए ऐसा करने का एकमात्र तरीका है। मैंने देखा कि यह प्रश्न/उत्तर एक वर्ष से अधिक पुराना है, क्या यहां कोई खबर है? – pdinklag

1

प्रतिबिंब चाल को छोड़कर, आप नहीं कर सकते। नोट, उदाहरण के लिए, विधि companion को स्कैला 2.8 संग्रहों पर कैसे परिभाषित किया गया है - यह वहां है कि कक्षा का एक उदाहरण साथी वस्तु प्राप्त कर सकता है, जो अन्यथा संभव नहीं है।

+0

क्या आप स्रोत के लिए एक लिंक जोड़ सकते हैं, कृपया? –

+0

http://lampsvn.epfl.ch/trac/scala/browser/scala/trunk/src/library/scala, हालांकि, उम्मीद है कि 2.8 के स्कालाडोक 2 में जल्द ही स्रोत के लिंक होंगे, जैसा कि पहले से ही 2.7 के साथ होता है। –

11

ऊपर थॉमस जंग के उत्तर में समायोजन: आप साथी [List.type] कहने के लिए बेहतर करेंगे क्योंकि ए) इसे संदर्भित करने का एक स्थिर तरीका होना चाहिए, नाम मैंगलिंग योजना पर निर्भर नहीं है और बी) आपको unerased प्रकार।

def singleton[T](implicit man: reflect.Manifest[T]) = { 
    val name = man.erasure.getName() 
    assert(name endsWith "$", "Not an object: " + name) 
    val clazz = java.lang.Class.forName(name) 

    clazz.getField("MODULE$").get(clazz).asInstanceOf[T] 
} 

scala> singleton[List.type].make(3, "a")      
res0: List[java.lang.String] = List(a, a, a) 
+0

बहुत अच्छा! अभी भी मेरे स्वाद के लिए थोड़ा गड़बड़ है लेकिन मैं इसका उपयोग कर सकता हूं ... – Dave

+0

यह सिर्फ 'List.make (3, "a")' से बेहतर कैसे है? ओपी स्ट्रिंग नाम – IttayD

+1

द्वारा ऑब्जेक्ट प्राप्त करना चाहता था धन्यवाद! यही वह है जिसकी तलाश में मैं हूं। यह निश्चित रूप से एक हैक है, लेकिन मैं जो कुछ करने में कामयाब रहा उससे कम गंदा है। –

34

स्केला 2.10 में हम इस

import scala.reflect.runtime.universe 

val runtimeMirror = universe.runtimeMirror(getClass.getClassLoader) 

val module = runtimeMirror.staticModule("package.ObjectName") 

val obj = runtimeMirror.reflectModule(module) 

println(obj.instance)