【问题标题】:Dealing with type erasure inside a Scala List处理 Scala 列表中的类型擦除
【发布时间】:2021-05-17 07:35:29
【问题描述】:

我有一些类似的课程

sealed trait Animal
case class Bird(name:String, birdField: BirdType) extends Animal
case class Cat(name:String, catField: CatType) extends Animal

然后是一个类

case class AnimalWrapper(id:Int, animal:Animal)

还有一个

List[AnimalWrapper]

例如,从AnimalWrapper 中提取Cat 并进行映射以访问其catField 的最佳方法是什么?

类似

animalWrapper.getThisAnimal[Cat](byName).map(_.catField)

我使用ClassTag 来获取列表中的任何动物,例如getThisAnimal[T <:Animal <:ClassTag]: Option[T],但是如果之前没有丑陋的演员表,我无法进行映射,这真的是不可接受的。
我还没有找到有什么有用的,或者至少是一个体面的解决方法,所以有什么想法吗?
谢谢

【问题讨论】:

  • 因为您的集合中有两种不同的类型,您需要对 Animal 类型进行模式匹配。如果你想避免 ClassCastException
  • 你想要的结果是什么?一个 List 与原始 List 中的所有 CatsList 的第一个 Cat?确保所有元素都是Cats?执行map,根据每个元素是 Cat 还是 Bird 来选择要执行的操作?
  • 一个Option[AnimalWrapper],我可以在它上面做birdFieldcatField而不需要任何演员,比如getThisAnimal[Cat].map(_.animal.catField)
  • 问题是AnimalWrapper 丢失了所有类型信息,所以即使您确定包装器中的内容是 Bird 编译器也不会接受它,除非你做了一个肮脏的演员。 - 也许我们可以修改包装类?或者,也许您根本不需要返回包装类,只需要返回动物和 id 的元组? - 另外,你提到了一个 Option 所以我猜你想要 List 中的第一个匹配(如果有的话)

标签: scala type-erasure


【解决方案1】:

您不需要强制转换,这就是模式匹配的用途:

case class AnimalWrapper(id:Int, animal:Animal) {

  def getThisAnimal[T <: Animal](implicit ct: ClassTag[T]): Option[T] = {
    animal match {
       case t: T => Some(t)
       case _    => None
    }
  }

}

【讨论】:

  • 问题不在于获取类,而在于访问其字段。因为你从List[Animalwrapper] 得到的——我想要这样——是一个AnimalWrapper,它不知道Animal 类型
  • @user2963757 我不明白您的期望,也许您可​​以提供更多详细信息或丰富您在原始问题中提供的代码示例。给我们输入和预期输出。
  • 一个 Option[AnimalWrapper],我可以在没有任何演员的情况下执行 birdField 或 catField,例如 getThisAnimal[Cat].map(_.animal.catField)
【解决方案2】:

我找到了解决方案。您必须将AnimalWrapper 设为泛型,例如AnimalWrapper[T &lt;: Animal]。然后是
def getThisAnimal[T &lt;:Animal:ClassTag]:Option[AnimalWrapper[T]] =
animalWrapper.collectFirst {
case AnimalWrapper(id, animal: T) =&gt; AnimalWrapper[T](id, animal)
}
现在您可以在没有任何演员表的情况下进行映射。希望能帮助别人。

【讨论】:

  • 使用 typeclass 可能比依赖类检查更好。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-05-28
  • 2020-07-27
  • 2012-08-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多