加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

Scala:根据类型参数过滤集合

发布时间:2020-12-16 09:52:50 所属栏目:安全 来源:网络整理
导读:基于这些对象的类型参数过滤对象集合的最佳方法是什么,假设我可以控制这两个类并且我需要协变过滤? 以下是一些无法正常运行的代码: trait Foocase class Foo1() extends Footrait ReadableFoo extends Foo {def field: Int}case class Foo2(field: Int,fla
基于这些对象的类型参数过滤对象集合的最佳方法是什么,假设我可以控制这两个类并且我需要协变过滤?

以下是一些无法正常运行的代码:

trait Foo
case class Foo1() extends Foo
trait ReadableFoo extends Foo {def field: Int}
case class Foo2(field: Int,flag: Boolean) extends ReadableFoo
case class Foo3(field: Int,name: String) extends ReadableFoo

case class Bar[+F <: Foo](foo: F)

val seq = Seq(
  Bar[Foo1](Foo1()),Bar[Foo2](Foo2(1,true)),Bar[Foo3](Foo3(1,"Fooz"))
)

// Should keep one
val first = seq collect {case x: Bar[Foo2] => x}

// Should keep two
val both = seq collect {case x: Bar[ReadableFoo] => x}

现在,我知道这是因为案例x:Bar [Foo1]在编译后通过类型擦除转换为案例x:Bar [_].我一直无法使用清单来解决这个问题.有没有办法将一个成员类型(即memberType = F)添加到Bar,我可以像case x if(x.memberType<:< ReadableFoo)=>一样打开它. X?

更新

0__很快找到了解决原始问题的好方法.稍微修改一下,case case字段本身就是一个集合:

case class Bar[+F <: Foo](foo: Seq[F])

val seq = Seq(
  Bar[Foo1](Seq(Foo1())),Bar[Foo2](Seq(Foo2(1,true))),Bar[ReadableFoo](Seq(Foo2(1,true),Foo3(1,"Fooz")))
)

// Should keep one
val first = seq collect {case x: Bar[Foo2] => x}

// Should keep two
val both = seq collect {case x: Bar[ReadableFoo] => x}

我不确定这是可能的,因为Seq可能是空的,因此没有要测试的元素.

解决方法

我不知道提取器技巧的类型检查所以我对你的第一个问题的初步解决方案会有所不同.我会为ReadableFoo提供一个提取器

object ReadableFoo { def unapply(x: ReadableFoo) = Some(x.field) }

然后你可以做到

val first = seq collect { case x @ Bar(Foo2(_,_)) => x }
val both  = seq collect { case x @ Bar(ReadableFoo(_)) => x }

但是对于您更新的代码,我认为您需要拖动清单.

case class Bar[+F <: Foo : Manifest](foo: Seq[F]) { 
    def manifest = implicitly[Manifest[_ <: F]] 
}

由于Bar是协变的而且Manifest是不变的,我们不能简单地承诺返回Manifest [F]但是F的某个子类型的Manifest(我想这是你在尝试使用清单时的问题?)
之后你就可以做到

val first = seq collect {case x if x.manifest <:< manifest[Foo2] => x}
val both = seq collect {case x if x.manifest <:< manifest[ReadableFoo] => x}

尽管如此,使用清单总是让人觉得有点笨拙.我会看看我是否可以使用不同的方法,并尽可能少地依赖类型匹配和具体化.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读