2009-12-16 26 views
22

Bir dize adıyla tanımlanan nesneyi (veya "tekil nesne" veya "tamamlayıcı nesne" ... sınıftan başka bir şey) kullanmalıyım. Ben varsa Başka bir deyişle,:Scalada dize adına göre nesne örneği alma

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

cevap

12

Scala hala bir yansıması API eksik:

package myPackage 
object myObject 

... sonra böyle bir şey yoktur.

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) 

Bu şekilde scala bağlıdır:

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) 

doğrudan sınıfını kullanabilirsiniz nesnesi türsüz arkadaşı almak için: arkadaşı nesne sınıfını yükleyerek arkadaşı nesnesinin bir örneğini alabilirsiniz java sınıflarına eşlenir.

+1

Kutsal inek gibi yapabilirsiniz. Bu sözdiziminin Scala özelliklerinin sabit bir parçası olup olmadığını biliyor musunuz (dilin herhangi bir yerinde olduğu gibi). Buna güvenmek kötü bir fikir gibi görünüyor. Ve amacım kodun daha temiz olmasını sağlamaktı * ... Teşekkürler! – Dave

+0

Daha önce de belirttiğimiz gibi, Scala'da yansıma API'sı yok, bu yüzden Scala spekleri tarafından kapsanmış olsun ya da olmasın, bunu yapmanın tek yolu budur. Bu sorunun farkına vardım/cevap bir yıldan fazladır, burada haber var mı? – pdinklag

1

Yansıma hilelerini kısıtlama, yapamazsınız. Örneğin, Scala 2.8 koleksiyonlarında companion yönteminin nasıl tanımlandığını not edin - bir sınıfın bir örneği, eşlik eden nesneyi alabilir, aksi halde mümkün değildir.

+0

Kaynağa bir link ekleyebilir misiniz, lütfen? –

+0

http://lampsvn.epfl.ch/trac/scala/browser/scala/trunk/src/library/scala, yine de, umuyoruz ki, 2.8'in Scaladoc 2'si yakında 2.7 ile olduğu gibi kaynağa bağlantılar içerecek. –

11

Yukarıdaki Thomas Jung'un cevabına uyum: companion [List.type] demek için daha iyi bir şey yaparsınız çünkü a) bunun adının mangling şemasına bağımlı olmamasına ve bunu b) tanımlanmamış tipler.

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

Çok güzel! Yine de benim zevklerim için biraz şanslıyım ama bunu kullanabilirim ... – Dave

+0

Bu nasıl daha iyi bir 'List.make (3, "a") 'dan daha iyi? OP – IttayD

+1

dize adıyla nesneyi almak istedim Teşekkürler! Tam olarak aradığım şey bu. Kesinlikle bir korsanlık, ama gelmeyi başardığımdan daha az kirli. –

34

scala 2.10 biz bu

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)