简体   繁体   English

Scala:避免类型擦除

[英]Scala: avoid type erasure

From the following code:从以下代码:

type Structure = Map[String, Any]

def getStructureSourceNames(structuresDesc: Structure): Iterable[String] = {
  val subColsDesc: Map[String, String] =
    structuresDesc.filter(_._2.isInstanceOf[String]).asInstanceOf[Map[String, String]]
  val subStructuresDesc: Map[String, Structure] = structuresDesc
    .filter(_._2.isInstanceOf[Map[String, Structure]])
    .asInstanceOf[Map[String, Structure]]

  subColsDesc.values ++ subStructuresDesc.values.flatMap(getStructureSourceNames(_))
}

I want to pass a recursive Map of (String -> String), ia.我想传递(字符串->字符串)的递归 Map,ia。 an example of Structure is:结构的一个例子是:

Map("test" -> Map(
        "newid" -> "id",
        "newstring" -> "string",
        "toto" -> Map("newdouble" -> "double")
      ),
      "otherid" -> "id")

The method getStructureSourceNames should return the list of "final" value, ia. getStructureSourceNames方法应该返回“最终”值的列表,ia。 browse the whole tree and for each leaft, get the String value.浏览整个树并为每个传单获取字符串值。

When I run this code, this drives me to:当我运行这段代码时,这驱使我:

Warning:(78, 32) non-variable type argument String in type scala.collection.immutable.Map[String,Structure] (the underlying of Map[String,Structure]) is unchecked since it is eliminated by erasure
  .filter(_._2.isInstanceOf[Map[String, Structure]])

Moreover, I don't like to use isInstanceOf / asInstanceOf.此外,我不喜欢使用 isInstanceOf / asInstanceOf。 By googling, I found that I could use pattern matching to check for the type, and get the Map with expected typing, but I can"t find how to do it.通过谷歌搜索,我发现我可以使用模式匹配来检查类型,并获得具有预期类型的 Map,但我找不到如何做到这一点。

Would you have an example of such code?你有这样的代码的例子吗?

There are 2 kinds of pattern matching:有2种模式匹配:

1) pattern matching on a sealed trait (good) 1) sealed trait上的模式匹配(好)

2) pattern matching where patterns involve matching with arbitrary classes and equality checks (not better than instanceOf checks) 2) 模式匹配,其中模式涉及与任意类匹配和相等性检查(不比instanceOf检查好)

To avoid 2) you need to make the type you want to match a sealed trait:为了避免2)你需要使你想要匹配一个密封特征的类型:

sealed trait ConfigValue
case class StringValue(v: String) extends ConfigValue
case class MapValue(map: Map[String, ConfigValue]) extends ConfigValue

val struct: ConfigValue = MapValue(Map("key1" -> StringValue("v1"),
                   "key2" -> MapValue(Map("sub" -> StringValue("val")))))

def allValues(s: ConfigValue): Iterable[String] = {
  s match {
    case StringValue(v) => Seq(v)
    case MapValue(map) => map.values.flatMap(v => allValues(v))
  }
}

println(allValues(struct))

By the way your structure looks similar to json.顺便说一句,您的结构看起来类似于 json。 Maybe you could reuse some json library.也许你可以重用一些 json 库。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM