gpt4 book ai didi

Scala 反射 - 基于特征加载或查找类

转载 作者:行者123 更新时间:2023-12-04 10:25:50 32 4
gpt4 key购买 nike

scala 反射 API (2.10) 是否提供更简单的方法来搜索加载的类并将列表过滤到实现定义特征的特定类?
IE;

trait Widget {
def turn(): Int
}

class Cog extends Widget {
def turn() = {
5
}
}

class Sprocket extends Widget {
def turn() = {
10
}
}

我想在类库中搜索任何扩展 Widget 并实例化这些类的东西。所以我最终会得到一个 CogSprocket 的实例。

我在 Java 中做了类似的迭代,遍历类目录,形成类名并使用 Class.forName 加载一个 Class 对象然后检查。我只是想知道 scala 反射 API 是否提供了更简单的搜索方式。到目前为止,我看到的所有示例都是从一个已知的类被实例化开始,而不是从搜索可用的类开始。

最佳答案

这就是 ServiceLoader 的用途。

我认为反射 API 确实可以更轻松地整理出您需要的内容(即,用于过滤而不是用于查询类加载器)。

如果用你的短语“搜索加载的类”,你的意思是已经加载的类,请参阅 this question 以获取它们。

你可以想象一个带有初始化程序的小部件库,它只是确保它知道的所有小部件类都被加载。然后客户端只需要知道初始化程序。

型式试验是一样的。

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"
}

您正在寻找带有类型参数的东西:
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 已经十年了,而且谁不需要复习:
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 中找到你想要的东西,但后来我结束了练习。
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 反射 - 基于特征加载或查找类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17490779/

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com