Scala:如何在编译时不知道类型的情况下调用带有类型参数和清单的方法?

2024-02-05

我有一个具有以下签名的函数:

myFunc[T <: AnyRef](arg: T)(implicit m: Manifest[T]) = ???

如果我在编译时不知道参数的确切类型,如何调用此函数?

例如:

val obj: AnyRef = new Foo()    // At compile time obj is defined as AnyRef,
val objClass = obj.getClass    // At runtime I can figure out that it is actually Foo
// Now I would need to call `myFunc[Foo](obj.asInstanceOf[Foo])`,
// but how would I do it without putting [Foo] in the square braces?

我想写一些逻辑上类似的东西:

myFunc[objClass](obj.asInstanceOf[objClass])

谢谢你!

UPDATE:

这个问题是无效的 - 正如@DaoWen、@Jelmo 和@itsbruce 正确指出的那样,我想做的事情完全是无稽之谈!我只是认真地思考了这个问题。 感谢你们!太糟糕了,我不能接受所有正确的答案:)

所以,这个问题是由以下情况引起的:

我在用Salat https://github.com/novus/salat用于将对象序列化为 BSON/JSON 表示形式或从 BSON/JSON 表示形式序列化的库。Salat has an Grater[T]用于序列化和反序列化的类。 该方法调用了反序列化来自 BSON 看起来是这样的:

val foo = grater[Foo].asObject(bson)

到这里,类型参数的作用就清楚了。我当时想做的是使用同一个刨丝器连载我的域模型中的任何实体。所以我写道:

val json = grater[???].toCompactJSON(obj)

我立即进行反思,但表面上并没有看到明显的解决方案。这是:

grater[Entity].toCompactJSON(obj)  // where Entity...

@Salat trait Entity                // is a root of the domain model hierarchy

有时候事情比我们想象的要容易得多! :)


看来,当我写这个答案时,问题的作者意识到他不需要解决Manifests 在运行时。然而,在我看来,这是完全合法的问题,我在编写 Yaml [反]序列化库时成功解决了这个问题,所以我将答案留在这里。


可以使用做你想做的事ClassTag甚至TypeTags。我不知道Manifest因为该 API 已被弃用,而且我还没有使用过它,但我相信使用清单会更容易,因为它们不像新的 Scala 反射那么复杂。供参考,Manifest的继任者是TypeTag.

假设您有以下功能:

def useClasstag[T: ClassTag](obj: T) = ...

def useTypetag[T: TypeTag](obj: T) = ...

然后你需要打电话obj: AnyRef作为参数,同时提供ClassTag or TypeTag for obj.getClass类作为隐式参数。

ClassTag是最简单的。您可以创建ClassTag直接来自Class[_]实例:

useClasstag(obj)(ClassTag(obj.getClass))

就这样。

TypeTag更难。您需要使用 Scala 反射从对象中获取一个对象,然后您必须使用 Scala 反射的一些内部功能。

import scala.reflect.runtime.universe._
import scala.reflect.api
import api.{Universe, TypeCreator}

// Obtain runtime mirror for the class' classloader
val rm = runtimeMirror(obj.getClass.getClassLoader)

// Obtain instance mirror for obj
val im = rm.reflect(obj)

// Get obj's symbol object
val sym = im.symbol

// Get symbol's type signature - that's what you really want!
val tpe = sym.typeSignature

// Now the black magic begins: we create TypeTag manually
// First, make so-called type creator for the type we have just obtained
val tc = new TypeCreator {
  def apply[U <: Universe with Singleton](m: api.Mirror[U]) =
    if (m eq rm) tpe.asInstanceOf[U # Type]
    else throw new IllegalArgumentException(s"Type tag defined in $rm cannot be migrated to other mirrors.")
}
// Next, create a TypeTag using runtime mirror and type creator
val tt = TypeTag[AnyRef](rm, tc)

// Call our method
useTypetag(obj)(tt)

正如你所看到的,这个机器相当复杂。这意味着只有在以下情况下才应该使用它really需要它,并且正如其他人所说,真正需要它的情况非常罕见。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Scala:如何在编译时不知道类型的情况下调用带有类型参数和清单的方法? 的相关文章

  • 类型擦除露出丑陋的头,如何规避?

    所以我有这个界面 public interface EventHandler
  • 使用 Akka 玩 2.5 - 找不到参数超时的隐式值:akka.util.Timeout

    我正在尝试使用 Play 2 5 测试 Akka 但遇到了一个似乎无法解决的编译错误 我正在关注 Play 文档中的此页面 https playframework com documentation 2 5 x ScalaAkka http
  • 是否有任何开源 Java 反射实用程序或 jar?

    是否有任何开源实用程序或 jar 用于处理 java 中的反射 我将方法动态传递给一个类 我想获取返回值 例如 class Department String name Employee employees public void setN
  • 阶乘的 Scala 排列

    我怎样才能找到n Scala 中某些字母的排列 Scala 2 9 RC1 scala gt abc permutations toList res58 List String List abc acb bac bca cab cba
  • 通用特征的隐式转换

    我正在实现一个数据结构 并希望用户能够使用任何类型作为密钥 只要他提供一个合适的密钥类型来包装它 我有这个关键类型的特质 这个想法是进行从基类型到键类型的隐式转换 反之亦然 实际上 只使用基类型 该特征看起来像这样 trait Key T
  • 如何捕获 Oozie Spark 输出

    有没有办法捕获spark的输出然后将其输入到shell上 我们当前正在使用 scala 创建 jar 文件 并希望我们的 Spark 输出成为 shell 输入 我的想法是使用 wf actionData spark XXXX var 我只
  • 在Python中检测re(regexp)对象

    我想知道什么是正确的 pythonic 向后和向前兼容的方法如何检查对象是否已编译re object isinstance方法不能轻易使用 而生成的对象声称是 sre SRE Pattern object gt gt gt import r
  • Scala 模式匹配变量绑定

    为什么提取器返回时不能以 样式绑定变量Option
  • 为什么 Go 中只有 int 而没有 float?

    在 Go 中 有这样的类型int这可能相当于int32 or int64取决于系统架构 我可以声明一个整数变量而不用担心它的大小 var x int 为什么没有这个类型float 这相当于float32 or float64取决于我的系统架
  • 使用 scala 集合 - CanBuildFrom 麻烦

    我正在尝试编写一个接受任何类型集合的方法CC 并将其映射到一个新的集合 相同的集合类型但不同的元素类型 我正在挣扎 基本上我正在尝试实施map but 不在集合本身上 问题 我正在尝试实现一个带有签名的方法 它看起来有点像 def map
  • Java 中的“Lambdifying”scala 函数

    使用Java和Apache Spark 已用Scala重写 面对旧的API方法 org apache spark rdd JdbcRDD构造函数 其参数为 AbstractFunction1 abstract class AbstractF
  • Parsec 函数“parse”和类“Stream”的类型签名

    约束条件是什么 Stream s Identity t 下面的类型声明是什么意思 parse Stream s Identity t gt Parsec s a gt SourceName gt s gt Either ParseError
  • scala play框架如何对异步控制器进行单元测试

    使用 Scala play 2 5 版并尝试遵循以下文档中的单元测试控制器指南 https www playframework com documentation 2 5 x ScalaTestingWithScalaTest https
  • 从通用对象访问字段变量

    我有两节课ClassOne and ClassTwo 更新公共字段data i e public class ClassOne public byte data new byte 10 Thread that updates data an
  • 如何在 Spark Dataframe 中显示完整的列内容?

    我正在使用 Spark csv 将数据加载到 DataFrame 中 我想做一个简单的查询并显示内容 val df sqlContext read format com databricks spark csv option header
  • Haskell 中的多态函数作为参数

    我有一个带有两个构造函数的 ADT 一个包裹着一个Double和一个包裹着Integer 我想创建一个函数 它采用一元函数Numtypeclass 并返回一个函数 该函数将该一元函数应用于我的 ADT 的内容 我试过这个 data X Y
  • 如何访问 Scala XML 中的父元素

    The scala xml包表示带有标记树节点的 XML 但是这棵树在 Scala 2 7 中是单向的吗 因为似乎没有办法访问Elem给定的父级Elem 这似乎同样适用于父母Document 例如 在 XOM 中你有getParent an
  • 按字符分割字符串

    scala 有一个标准的分割字符串的方法StringOps split 但它的行为有点让我惊讶 演示一下 使用快捷便利功能 def sp str String str split toList 以下表达式全部计算结果为 true sp Li
  • Scala 交互式解释器 (REPL) - 如何将输出重定向到文本文件?

    是否可能 如果可能 是如何做到的 通常 gt and gt gt 在 Windows 或 Linux 命令行上工作的命令在这种情况下不起作用 您可以从控制台以编程方式执行此操作 import java io FileOutputStream
  • 必须包含 log4J,但它会导致 Apache Spark shell 中出现错误。如何避免错误?

    由于我必须将 jar 包含到 Spark 代码中 因此我想请求帮助找出解决此问题而不删除 log4j 导入的方法 简单代码如下 cp symjar log4j 1 2 17 jar import org apache spark rdd v

随机推荐