【问题标题】:Is dynamic scala generics possible?动态scala泛型是否可能?
【发布时间】:2017-03-15 22:07:39
【问题描述】:

我有一个方法,它返回一个 Object 类型的包装对象,该对象最初是 String、Int、Long、Boolean 等

我还有一组重载的方法,它们是为每个单独的类而不是 Object 类型量身定制的

我的目标是构建一个通用实现,它将检查类型为 Object 的对象,并将其显式转换为适当的底层类,以特定的预定顺序检查给定的一组类类型。第一个匹配的类将保证方法调用将对象强制转换为特定的底层类。

这是一个基于复制/粘贴的代码示例,我试图实现但希望它在循环或其他设备中表达,其中类型是从列表或其他一些收集设备中检查的,以便此列表可以定义一次,并在许多情况下使用匹配模式:

val o : Object = "string"
if (o.isInstanceOf[String] ) f(o.asInstanceOf[String] ) else
if (o.isInstanceOf[Boolean]) f(o.asInstanceOf[Boolean]) else
if (o.isInstanceOf[Int]    ) f(o.asInstanceOf[Int]    ) else
if (o.isInstanceOf[Double] ) f(o.asInstanceOf[Double] )

我想要的(注意,以下显然不是scala,但是……也许有一种方法可以在scala中表达类似的模式)

val o : Object = "string"
val t = List(String,Boolean,Int,Double)
for (T <- t) if(o.isInstanceOf[T]) f(o.asInstanceOf[T])

任何帮助将不胜感激

这是一个更具体的例子:

val n : org.neo4j.graphdb.Node = ...
var j : com.fasterxml.jackson.databind.node.ObjectNode = ...
val p = "someProperty"
val o = n.getProperty(p) // returns Object (do not confuse w ObjectNode)
if (o.isInstanceOf[String ]) j.put(p,o.asInstanceOf[String ]) else
if (o.isInstanceOf[Boolean]) j.put(p,o.asInstanceOf[Boolean]) else
if (o.isInstanceOf[Int]    ) j.put(p,o.asInstanceOf[Int]    ) else
...

【问题讨论】:

  • 您可能正在寻找typeclasses。您能否提供更多关于您希望对不同对象执行何种操作的详细信息?
  • 我通过阅读以下smartjava.org/content/… 稍微了解了typeclasses。而且我仍然看不到如何在不必为每个不同的 f() 进行大量编码的情况下利用来实现预期的目标。请注意,在我的例子中 f() 是来自 jar 中某个黑盒类的方法,并且有许多不同类型的 f() 带有不同的签名,但它们都以相似的模式运行。我想做的就是调用任何类似 f() 的方法,并将对象转换为适当的类型(我为每个 f() 编写一个包装器)
  • 我想我理解您想要达到的目标,但如果您能指定最终意图,即“为什么”,那将真的很有帮助。在“转换”这些值之后,您要执行哪些操作?知道了这一点,我可能会提出一个更好的答案。
  • 我正在使用我将其视为黑盒的 API,一个 API 返回一个 Object 类型的变量(尽管该对象实际上最初在 API 中创建为 String、Boolean、Int 等),我有另一组黑盒 API,它们接受 String 或 Boolean 或 Int,但不接受 Object,并且自动转换不起作用(两个 API 都是 Java),我正在寻找一种简洁的方法来调用带有返回值的第二个 API从第一个。简而言之,调用api2(api1()) 和强制转换类型,因为我必须这样做。不能修改任何一个 api,编写完整的包装器也是太多的工作。
  • 你提到的事情(不能修改任何一个 api,不能做完整的包装器等)肯定暗示了类型类。但是你仍然没有给出一个具体的例子(你想调用什么方法),这是展示类型类解决方案如何工作所需要的。

标签: scala generics


【解决方案1】:

如果我理解正确,我认为您正在寻找的是模式匹配:

val object: Any = "string"
object match {
  case o: String  => // do some string operation on `o`
  case o: Boolean => // do some boolean operation on `o`
  case o: Int     => ...
  case o: Double  => ...
}

当然,模式匹配可以以更精细的方式使用。希望对您有所帮助:)

【讨论】:

  • 不,不是真的,或者至少我不知道如何利用模式匹配,这样我就不必像我拥有的​​类型一样多次重复函数调用 f()。我将尝试在原始问题中澄清这一点。
  • 我明白了。既然您提到了它,您应该按照@Alvaro Carrasco 的建议使用类型类。请添加有关操作的更多详细信息,以便我们可以想象类型类的外观:) 在此处查看示例 - eed3si9n.com/herding-cats/Eq.html
猜你喜欢
  • 1970-01-01
  • 2011-12-17
  • 1970-01-01
  • 2013-07-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-25
  • 2020-11-27
相关资源
最近更新 更多