动态加载Scala对象

动态加载Scala对象,scala,dynamic,classloader,dynamic-class-loaders,companion-object,Scala,Dynamic,Classloader,Dynamic Class Loaders,Companion Object,我有许多操作数据库的对象(不是类),我想创建一个较小的助手类,这样我就可以执行类似javamy.helper.class my.database.class的操作,并执行run方法 例如,它编译 trait A extends Runnable class B extends A { def run() = println("run") } object Test extends App { Class.forName(args(0)).newInstance().asInstanceOf[

我有许多操作数据库的对象(不是类),我想创建一个较小的助手类,这样我就可以执行类似
javamy.helper.class my.database.class
的操作,并执行
run
方法

例如,它编译

trait A extends Runnable
class B extends A { def run() = println("run") }
object Test extends App {
  Class.forName(args(0)).newInstance().asInstanceOf[A].run()
}
然后做我所期望的

$scala Test B
run
这也编译了

trait A extends Runnable
object B extends A { def run() = println("run") }
object Test extends App {
  Class.forName(args(0)).newInstance().asInstanceOf[A].run()
}
但这种情况会发生:

$scala Test B
java.lang.InstantiationException: B
    at java.lang.Class.newInstance(Class.java:418)
    at Test$.delayedEndpoint$Test$1(Test.scala:9)
    at Test$delayedInit$body.apply(Test.scala:8)
    at scala.Function0$class.apply$mcV$sp(Function0.scala:40)
    at scala.runtime.AbstractFunction0.apply$mcV$sp(AbstractFunction0.scala:12)
    at scala.App$$anonfun$main$1.apply(App.scala:76)
    at scala.App$$anonfun$main$1.apply(App.scala:76)
    at scala.collection.immutable.List.foreach(List.scala:383)
    at scala.collection.generic.TraversableForwarder$class.foreach(TraversableForwarder.scala:35)
    at scala.App$class.main(App.scala:76)
    at Test$.main(Test.scala:8)
    at Test.main(Test.scala)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:483)
    at scala.reflect.internal.util.ScalaClassLoader$$anonfun$run$1.apply(ScalaClassLoader.scala:68)
    at scala.reflect.internal.util.ScalaClassLoader$class.asContext(ScalaClassLoader.scala:31)
    at scala.reflect.internal.util.ScalaClassLoader$URLClassLoader.asContext(ScalaClassLoader.scala:99)
    at scala.reflect.internal.util.ScalaClassLoader$class.run(ScalaClassLoader.scala:68)
    at scala.reflect.internal.util.ScalaClassLoader$URLClassLoader.run(ScalaClassLoader.scala:99)
    at scala.tools.nsc.CommonRunner$class.run(ObjectRunner.scala:22)
    at scala.tools.nsc.ObjectRunner$.run(ObjectRunner.scala:39)
    at scala.tools.nsc.CommonRunner$class.runAndCatch(ObjectRunner.scala:29)
    at scala.tools.nsc.ObjectRunner$.runAndCatch(ObjectRunner.scala:39)
    at scala.tools.nsc.MainGenericRunner.runTarget$1(MainGenericRunner.scala:72)
    at scala.tools.nsc.MainGenericRunner.process(MainGenericRunner.scala:94)
    at scala.tools.nsc.MainGenericRunner$.main(MainGenericRunner.scala:103)
    at scala.tools.nsc.MainGenericRunner.main(MainGenericRunner.scala)
Caused by: java.lang.NoSuchMethodException: B.<init>()
    at java.lang.Class.getConstructor0(Class.java:2971)
    at java.lang.Class.newInstance(Class.java:403)
    ... 28 more

但它也失败了。我知道我可以将所有这些静态对象编入类中,但这在这个应用程序中没有意义,因此我特别寻找一种优雅的方法来实现这一点。

我个人认为最优雅的方法是不要动态加载这样的东西。指定有效的输入是否真的那么困难?这使得
A
实例的来源具有更大的灵活性

object Test extends App {
  args(0) match {
    case "B" => B
    case "C" => 
      val someOtherConfig = args(1)
      new C(someOtherParam)
    case other => throw new Exception("invalid input")
  } run
}

我将使用解析参数

B$
的构造函数是私有的,这就是代码失败的原因。它是私有的,因此只创建一个实例。这一个实例可以通过静态
模块$
@wingedsubmariner访问-给定
对象Foo{}
,我如何使用
模块$
从字符串
“com.Foo$”
获取实际的单例实例?@KevinMeredith从字符串获取?这需要反思。我想提出一个新的问题。是的,我知道这会奏效,但我希望有一个更好的方法来做这件事,而不是长时间的,可能是非穷尽的模式匹配。
object Test extends App {
  args(0) match {
    case "B" => B
    case "C" => 
      val someOtherConfig = args(1)
      new C(someOtherParam)
    case other => throw new Exception("invalid input")
  } run
}