通过通用键和值从地图中获取实际类型

问题描述 投票:0回答:1

首先是一些Scala代码示例:

trait Key[+T]
trait Value[+T]

case class StringKey(key: String) extends Key[String]
case class IntKey(key: Int) extends Key[Int]

case class StringValue(value: String) extends Value[String]
case class IntValue(value: Int) extends Value[Int]

case class ValueHolder(sources: Map[Key[_], Value[_]]) {
  def processSources(): Unit = {
    sources.map{ case (key, value) =>
      // get actual key and value, and process
    }
  }
}

基本上我有一个从通用键到泛型值的映射,我需要迭代键值对并对实际对象进行操作。例如,如果当前值实际上是StringValue,我想对StringValue对象进行操作。有没有办法做到这一点?

scala generics scala-collections
1个回答
0
投票

是。当StringValue出现时,使用模式匹配或使用部分函数收集结果。

首先,我想你错过了StringKey extends Key[String]T等的协方差......

下面的代码说明了所需的内容。

trait Key[+T]

trait Value[+T]

case class StringKey(key: String) extends Key[String]
case class IntKey(key: Int) extends Key[Int]

case class StringValue(value: String) extends Value[String]
case class IntValue(value: Int) extends Value[Int]

假设上述情况

case class ValueHolder(sources: Map[Key[_], Value[_]]) {

  def processSources(): Unit = {
    sources
     .collect { case (_, StringValue(str)) => str }
     .foreach(println)
  }

}

Scala REPL

scala> :paste
// Entering paste mode (ctrl-D to finish)


    trait Key[+T]

    trait Value[+T]

    case class StringKey(key: String) extends Key[String]
    case class IntKey(key: Int) extends Key[Int]

    case class StringValue(value: String) extends Value[String]
    case class IntValue(value: Int) extends Value[Int]

// Exiting paste mode, now interpreting.

defined trait Key
defined trait Value
defined class StringKey
defined class IntKey
defined class StringValue
defined class IntValue

scala> :paste
// Entering paste mode (ctrl-D to finish)

case class ValueHolder(sources: Map[Key[_], Value[_]]) {

      def processSources(): Unit = {
        sources
         .collect { case (_, StringValue(str)) => str } // extracted string value ready to be operated.
         .foreach(println)
      }

    }

// Exiting paste mode, now interpreting.

defined class ValueHolder

Output

scala> ValueHolder(Map(StringKey("fruit") -> StringValue("apple")))
res2: ValueHolder = ValueHolder(Map(StringKey(fruit) -> StringValue(apple)))

scala> ValueHolder(Map(StringKey("fruit") -> StringValue("apple"))).processSources()
apple

通常,您可以迭代键值对

给予sources: Map[Key[_], Value[_]]

Process if the value is string value

sources.map { case (key, value) =>
  value match {
    case stringValue: StringValue => processValue(stringValue)
    case _ => fallbackValue
  }
}

更好的方法是使用collect

sources.collect { case (_, value: StringValue) => processValue(value) }
© www.soinside.com 2019 - 2024. All rights reserved.