Scala 反射 - 基于特征加载或查找类 [英] Scala Reflection - Loading or finding classes based on trait
问题描述
Scala 反射 API (2.10) 是否提供更简单的方法来搜索加载的类并将列表过滤到实现定义特征的特定类?即;
Does the scala reflection API (2.10) provide any easier means of searching the loaded classes and filtering the list to specific classes which implement a defined trait? ie;
trait Widget {
def turn(): Int
}
class Cog extends Widget {
def turn() = {
5
}
}
class Sprocket extends Widget {
def turn() = {
10
}
}
我想在类库中搜索任何扩展 Widget 并实例化这些类的东西.所以我最终会得到一个 Cog
和 Sprocket
的实例.
I want to search the class library for anything that extends Widget and instantiate those classes. So I would end up with an instance of Cog
and Sprocket
.
我在 Java 中做了类似的迭代,遍历类目录,形成类名并使用 Class.forName 加载一个 Class 对象然后检查.我只是想知道 scala 反射 API 是否提供了更简单的搜索方式.到目前为止,我看到的所有示例都是从实例化已知类开始,而不是从搜索可用类开始.
I've done similar in Java iterating through the class directories, forming class names and using Class.forName to load a Class object to then check. I'm just wondering if the scala reflection API gives any easier way to search. All examples I've seen thus far have always started from a known class being instantiated, and not from searching over available classes.
推荐答案
这就是 ServiceLoader
的用途.
我认为反射 API 确实可以让您更轻松地整理出您需要的内容(即用于过滤而不是用于查询类加载器).
I think the reflection API does make it easier to sort out what you need (i.e., for filtering but not for querying the class loader).
如果用你的短语搜索加载的类",你的意思是已经加载的类,请参阅这个问题 用于获取它们.
If, by your phrase, "searching the loaded classes", you really mean classes that are already loaded, see this question for getting them.
你可以想象一个带有初始化程序的小部件库,它只是确保它知道的所有小部件类都被加载.那么客户端只需要知道初始化器即可.
You could imagine a widgets library with an initializer that just ensures that all the widget classes it knows about are loaded. Then the client only needs to know the initializer.
型式测试相同.
val need = typeOf[Whatsit[Cog]]
for (x <- (ServiceLoader load classOf[Whatsit[_]]).asScala) {
val im = currentMirror reflect x
if (im.symbol.toType weak_<:< need)
Console println s"$x is what I need"
else
Console println s"$x is not what I need, I'm looking for a $need"
}
在何处查找带有类型参数的内容:
Where you're looking for something with type parameters:
trait Whatsit[+A <: Widget] {
def widget: A
}
class Engine extends Whatsit[Cog] {
def widget = new Cog
}
class FlyWheel extends Whatsit[Sprocket] {
def widget = new Sprocket
}
示例:
widgets.Engine@f9da0cd is what I need
widgets.FlyWheel@4cfdbb9f is not what I need, I'm looking for a widgets.Whatsit[widgets.Cog]
如果您使用 ServiceLoader
已经十年了,而且谁不需要复习:
In case it's been ten years since you used ServiceLoader
, and who doesn't need a refresher:
apm@mara:~/tmp$ ls -R META-INF
META-INF:
MANIFEST.MF services
META-INF/services:
widgets.Whatsit widgets.Widget
apm@mara:~/tmp$ cat META-INF/services/widgets.Widget
widgets.Cog
widgets.Sprocket
apm@mara:~/tmp$ cat META-INF/services/widgets.Whatsit
widgets.Engine
widgets.FlyWheel
东西:
package widgets
trait Widget {
def turn(): Int
override def toString = s"Widget ${getClass.getSimpleName}"
}
class Cog extends Widget {
def turn() = 5
}
class Sprocket extends Widget {
def turn() = 10
}
trait Whatsit[+A <: Widget] {
def widget: A
override def toString = s"Whatsit ${getClass.getSimpleName} of $widget"
}
class Engine extends Whatsit[Cog] {
def widget = new Cog
}
class FlyWheel extends Whatsit[Sprocket] {
def widget = new Sprocket
}
比较 Scala 和 Java.我本来想了解 getGenericInterfaces
有多少 LOC 并在 Scala 中找到你想要的东西,但后来我结束了练习.
Comparing Scala and Java. I was going to get a sense of how many LOC to getGenericInterfaces
and find what you want in Scala, but then I put an end to the exercise.
package findwidgets
import reflect._
import reflect.runtime.universe._
import reflect.runtime.currentMirror
import scala.collection.JavaConverters._
import java.util.ServiceLoader
object Test extends App {
import widgets.{ Widget, Whatsit, Cog }
val ws = (ServiceLoader load classOf[Widget]).asScala
for (w <- ws) {
Console println s"Turn a ${w.getClass} by ${w.turn}"
}
val need = typeOf[Whatsit[Cog]]
for (x <- (ServiceLoader load classOf[Whatsit[Cog]]).asScala) {
val im = currentMirror reflect x
if (im.symbol.toType weak_<:< need)
Console println s"$x is what I need"
else
Console println s"$x is not what I need, I'm looking for a $need"
// java says:
if (classOf[Whatsit[Cog]] isAssignableFrom x.getClass)
Console println s"Um, OK, I'll take the $x"
else
Console println s"${classOf[Whatsit[Cog]]} isn't ass'able from ${x.getClass}"
}
}
这篇关于Scala 反射 - 基于特征加载或查找类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!