【问题标题】:Is there a way to call a member in a generic type in Scala有没有办法在Scala中调用泛型类型的成员
【发布时间】:2019-04-30 03:25:58
【问题描述】:

我正在尝试从泛型类型调用成员,这是运行该函数的原始方式

SourceStruct 是我想用T 之类的东西替换的对象。

override def process(t: SourceStruct, runtimeContext: RuntimeContext, requestIndexer: RequestIndexer): Unit = {
        val json = new util.HashMap[String, String]()
        json.put("time", t.rating.toString)
        json.put("userId", t.userId.id.toString)
        json.put("itemId", t.itemId.id)

        requestIndexer.add(request)
      }

当我将SourceStruct 替换为T 时,如何调用t.userId?

override def process(t: T, runtimeContext: RuntimeContext, requestIndexer: RequestIndexer): Unit = {
      val json = new util.HashMap[String, String]()
//      json.put("userId", t.userId.id)
//      json.put("itemId", t.itemId.id)
//      json.put("rating", t.rating.toString)

      val request = Requests
        .indexRequest()
        .index(index)
        .`type`(indexType)
        .source(json)
      requestIndexer.add(request)
    }

提前致谢

我可以通过使用获得会员

typeOf[T].members.collect {
case m: MethodSymbol if m.isCaseAccessor => m
}.toList

但还是不知道上面的问题


编辑:

例如:

case class ExampleClass(x: Int, y: Int)
case class ExampleClass2(xx: Int, yy: Int)

那么在流程函数中,如何给成员赋值

override def process(t: T, ...) = {
    //t.x = 10 or t.xx = 10 ???
}

已解决

Convert Any Class to HashMap

【问题讨论】:

  • 如果您有T,您希望如何调用其中的任何成员?它可以是任何东西,比如Int 甚至Nothing。如果您想要一个对象的特定成员,为什么要使其成为通用对象? - 您可能只需要类型的子集,如果是这样并且它们是相关的并且您管理所有这些类型,可能 subtyping 就是您所需要的,为接口编码方法。如果它们不相关或者你不能修改它们,你可以使用 typeclasses 代替,使用抽象提供的函数编码方法。
  • @LuisMiguelMejíaSuárez 感谢您的回复,但子类型不是我想要的。实际上,我什至不知道它是否可行。我只是在我的问题中添加一个示例
  • 你使用什么 scala 版本?
  • @talex 版本 2.12.7
  • 在ExampleClass 的示例字段中是只读的。

标签: scala reflection generic-programming


【解决方案1】:

查看您的代码,您似乎不想“调用泛型类型的成员”,似乎您想将案例类转换为HashMap。

Case class to map in Scala

【讨论】:

  • 感谢您的链接。这正是我想做的事情
  • @XuYan 如果这回答了您的问题,请考虑投票和/或将其标记为已接受的答案。见this。
  • @LuisMiguelMejíaSuárez 我做到了,但我认为我需要至少 15 个声望才能投票
【解决方案2】:

这里是小sn-p

  case class Foo(bar: String)

  val f: Object = Foo("a")

  val barField = f.getClass.getDeclaredField("bar")

  barField.setAccessible(true)
  val value = barField.get(f).asInstanceOf[String]

  print(value)

赋值使用

 barField.set(f, "new value")

【讨论】:

  • 我刚刚添加了一个示例,希望它可以使问题变得清晰。进程函数不知道通用函数T,所以我不能使用asInstanceOf[String],也不能将我的自定义类作为接口。
  • 添加了显示如何赋值的代码。如果您不知道字段的类型,您仍然可以读取值,但是很难分配它,因为您必须具有正确类型的值。
  • case class Foo(bar: String, boo: String) val f = Foo("a", "b") val barField = f.getClass.getDeclaredField(???) 我不知道“bar”在这部分,那我怎么才能得到barField?
  • 您可以通过f.getClass.getDeclaredFields()获得所有字段的列表
猜你喜欢
  • 1970-01-01
  • 2022-06-21
  • 2022-06-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多