2012-01-15 16 views
18

, bu arada (.jar dosyası) dış sınıfını yükleyin.Scala Dinamik nesne/sınıf yükleme Java'da

====================

Şimdi Scala aynı şeyi yapmak istiyorum.

trait Module { 
    def name: String 
} 

object Module { 
    lazy val ModuleClassName = "my.module.ExModule" 
} 

Ben Module uzanan bir modül yazmak, sonra module.jar bunu derlemek: Bir trait adında Module ( Module.scala) sahip

var classLoader = new URLClassLoader(Array[URL](
    new File("module.jar").toURI.toURL)) 
var clazz = classLoader.loadClass(Module.ModuleClassName) 
:

package my.module 

import Module 

object ExModule extends Module {} 

Sonra bu kodla yüklemek

İyi çalışıyor. Bunu test ederseniz

java.lang.InstantiationException: my.module.ExModule 

: Ben yeni bir örneğini oluşturmak Ama eğer, bu durum alıyorum

-> hep false dönün.

Bu konuda bana yardımcı olabilir misiniz?

Düzenlendi

Ben ExModule bir object (değil class) olduğu için sanırım. Ancak, class olarak değiştirdiğimde ve classLoader.loadClass(...), java.lang.NoClassDefFoundError yükseltir. Sanırım, ExModule, trait'dan uzatıldı.

Kafam karıştı. Lütfen biri bana yardım edebilir mi?

Düzenlenen

clazz.isInstanceOf[Class[Module]]//or Class[Byte], or Class[_]... 

döner true.

+0

Sanırım bir sınıf yapmakla daha yakın olursunuz (ClassNotFoundException'ı aldığınızda). Module.jar 'a başvuruda bulunduğunuzda yolun doğru olduğundan emin misiniz? Bir özellikten uzatılmasının bir fark yaratmaması gerekir - ExModule bir sınıftır (bu durumda). –

+0

Evet 'module.jar' yolunun doğru olduğundan eminim. "ClassLoader.loadClass (...)" yöntemi iyi çalışıyor (ExModule '' object' ise). –

+0

Derlenmiş bayt koduyla (javap veya benzeri) bakabilir misiniz? Scalac, her yerde $ s ve diğer garip isimleri eklemenin eğlenceli bir alışkanlığı var ve belki de ExModule'ınızın derlenmiş versiyonda başka bir ismi var. Ayrıca, scalac’ın java kodunu scala’nızda yazdırabilmesini isteyebilirsiniz (şimdi sadece seçeneği hatırlamıyorum). – Rogach

cevap

8

Hata ... Ben cevap aldım.

Ben Scala takımı için doğru bir yol sağlar önce bu şekilde geçici olduğunu tahmin object/class/trait ... harici bir kavanoz dosyasından yükleyin. Ya da doğru yolu bulamadığım için. Ama şu anda bu problemden kurtulmamı sağlıyor. Bir sınıf olarak daha iyi bir tasarım ExModule olur tüm :-)

Düzenlendi

var

var classLoader = new java.net.URLClassLoader(
    Array(new File("module.jar").toURI.toURL), 
    /* 
    * need to specify parent, so we have all class instances 
    * in current context 
    */ 
    this.getClass.getClassLoader) 

/* 
* please note that the suffix "$" is for Scala "object", 
* it's a trick 
*/ 
var clazzExModule = classLoader.loadClass(Module.ModuleClassName + "$") 

/* 
* currently, I don't know how to check if clazzExModule is instance of 
* Class[Module], because clazzExModule.isInstanceOf[Class[_]] always 
* returns true, 
* so I use try/catch 
*/ 
try { 
    //"MODULE$" is a trick, and I'm not sure about "get(null)" 
    var module = clazzExModule.getField("MODULE$").get(null).asInstanceOf[Module] 
} catch { 
    case e: java.lang.ClassCastException => 
    printf(" - %s is not Module\n", clazzExModule) 
} 

. Kavanoz dosyadan yükleyerek sonra ben gibi kontrol edebilirsiniz:

var clazz = classLoader.loadClass(Module.ModuleClassName) 
if (classOf[Module].isAssignableFrom(clazz)) 
    ... 

Not:

Sen Onların tersini yapamaz:

if (clazz.isAssignableFrom(classOf[Module])) 

Module çünkü Bu durumda bir trait/object, isAssignableFrom() çalışmayacaktır.

0
+0

değiştiricileri ile sınıf my.module.ExModule $ bir üyesi Teşekkürler, ben bunu göndermeden önce bu soruyu okudum. Ama hala şaşkınım :-(Tekrar deniyorum ... –