如果我知道一个对象的类名,如何获取它并调用它的方法?
我有一个特征,名为Init
:
package test
trait Init {
def init(): Any
}
有一些类和一个对象,扩展了这个特征:
package test
object Config extends Init {
def init() = { loadFromFile(...) }
}
class InitDb extends Init {
def init() = { initdb() }
}
当应用程序启动时,我会找到所有扩展Init
的类和对象,并调用它们的 init 方法。
package test
object App {
def main(args: Array[String]) {
val classNames: List[String] = findAllNamesOfSubclassOf[Init]
println(classNames) // -> List(test.Config$, test.InitDb)
classNames foreach { name =>
Class.forName(name).newInstance().asInstanceOf[Init].init() // ***
}
}
}
请注意“*”行。对于test.InitDb
来说,没问题。但是对于test.Config$
,当newInstance()
时,它会抛出一个异常,表示我们无法访问其私有方法。
我的问题是,如何获取该对象并运行其 init 方法?
I have a trait, named Init
:
package test
trait Init {
def init(): Any
}
There are some classes and an object, extends this trait:
package test
object Config extends Init {
def init() = { loadFromFile(...) }
}
class InitDb extends Init {
def init() = { initdb() }
}
When app has started, I will find all classes and objects which extends Init
, and invoke their init
method.
package test
object App {
def main(args: Array[String]) {
val classNames: List[String] = findAllNamesOfSubclassOf[Init]
println(classNames) // -> List(test.Config$, test.InitDb)
classNames foreach { name =>
Class.forName(name).newInstance().asInstanceOf[Init].init() // ***
}
}
}
Please note the "*" line. For test.InitDb
, it's OK. But for test.Config$
, when newInstance()
, it throws an exception said we can't access its private method.
My problem is, how to get that object, and run its init
method?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
在 Scala 中这样做通常没有什么意义。只需将一些代码放入任何
对象
的主体中,它就会在该对象首次初始化时执行,从而节省了预初始化所有内容所带来的令人讨厌的性能损失。但一般来说,查找特定类型的所有子类需要完整的类路径扫描。有几个库可以做到这一点,但最常见的一个是 Apache 的 commons-discover< /a>
然而...这是动态代码,它使用反射,而且它确实不符合习惯。 Scala 有比这更锋利的工具,所以请不要尝试使用如此暴力的钝器!
There's usually little point to doing this in Scala. Just put some code in the body of any
object
and it'll be executed when that object is first initialised, saving you the nasty performance hit of pre-initialising everything.In general though, finding all subclasses of a particular type requires a full classpath scan. There are a few libraries to do this, but one of the more common is Apache's commons-discover
However... This is dynamic code, it uses reflection, and it's really NOT idiomatic. Scala has sharper tools than that, so please don't try and swing the blunt ones with such violence!
我不完全同意凯文的观点。但也有一些例外。例如,我编写了一个 Scala 桌面应用程序。我将核心和模块分成两部分。在启动时,核心将所有模块加载到 GUI 中。此时核心只获取模块的名称,不需要初始化某些东西。然后我将所有模块的初始化代码放入
init()
函数中。当用户执行该模块时将调用该函数。@Freewind:关于Scala中的反射,在Java中是完全一样的。请注意,与反射一起使用的 Java 方法用于 Java 对象,而不是 Scala。我为我的英语感到抱歉。我的意思是这些方法不能与 Scala
object
、trait
一起使用。例如:
但是你不能以相反的方式做:
因为
Init
是一个trait
,而Java方法isAssignableFrom(Class)< /code>
不知道
特质
。我不确定我的问题对您是否有用,但就在这里。
I don't totally agree with Kevin. There are some exceptions. For example I wrote a Scala desktop app. I split the core and the modules into two parts. At startup time the core loads all modules into GUI. At that time the core just gets the name of modules, it doesn't need to initialize something. Then I put all module's init code in an
init()
function. That function will be called when user executes the module.@Freewind: About reflection in Scala, it's absolutely the same in Java. Just please note that the methods from Java which are used with reflection, are used for Java objects - not Scala. I'm sorry for my English. I mean those methods can not work with Scala
object
,trait
.For example:
But you can not do it the opposite way:
Because
Init
is atrait
, and Java methodisAssignableFrom(Class)
doesn't knowtrait
.I'm not sure if my question is useful for you, but here it is.