Scala多态方法-{case x:T => x}返回所有类型

Fil*_*279 1 methods polymorphism scala

我不明白为什么在Scala多态方法无法按我预期的那样工作。

让我们有方法:

def sth[T](list: Iterable[Any]): List[T] = {
list.collect({case s:T => s}).toList
}
Run Code Online (Sandbox Code Playgroud)

我不希望从列表中仅获取布尔值。所以我会写:

val out = sth[Boolean](List(true, false, 2.0, 2, 4, 12.3))
Run Code Online (Sandbox Code Playgroud)

我所期望的是List(true, false),IntelIJ向我显示了以下out实例:List[Boolean]但是此方法返回给我的是我的输入列表:List(true, false, 2.0, 2, 4, 12.3)

我也尝试过,list.filter(s => s.isInstanceOf[T])但结果相同。

在此处输入图片说明

我有点困惑。你能解释一下我做错了什么吗?

Mar*_*lic 8

由于类型擦除检查

case s:T => ...
Run Code Online (Sandbox Code Playgroud)

变成像

if (s.isInstanceOf[Object]) ...
Run Code Online (Sandbox Code Playgroud)

如编译器警告消息所示

 warning: abstract type pattern T is unchecked since it is eliminated by erasure
    list.collect({case s:T => s}).toList
Run Code Online (Sandbox Code Playgroud)

尝试像这样提供ClassTag

import scala.reflect.ClassTag

def collect[T: ClassTag](list: Iterable[Any]): List[T] = {
  list.collect({ case s: T => s }).toList
}

collect[Boolean](List(true, false, 2.0, 2, 4, 12.3))
collect[Double](List(true, false, 2.0, 2, 4, 12.3))
Run Code Online (Sandbox Code Playgroud)

哪个输出

res0: List[Boolean] = List(true, false)
res1: List[Double] = List(2.0, 12.3)
Run Code Online (Sandbox Code Playgroud)

由于此处解释一些编译器魔术,该方法起作用。

这是我们自己的类型类解决方案

trait Collectable[T] {
  def collect(list: Iterable[Any]): List[T]
}

object Collectable {
  def collect[T](list: Iterable[Any])(implicit ev: Collectable[T]): List[T] =
    ev.collect(list)

  implicit val booleanCollect: Collectable[Boolean]  = 
    (list: Iterable[Any]) => list.collect({ case s: Boolean => s }).toList

  implicit val doubleCollect: Collectable[Double] = 
    (list: Iterable[Any]) => list.collect({ case s: Double => s }).toList
}

import Collectable._

collect[Boolean](List(true, false, 2.0, 2, 4, 12.3))
collect[Double](List(true, false, 2.0, 2, 4, 12.3))
Run Code Online (Sandbox Code Playgroud)

哪个输出

res0: List[Boolean] = List(true, false)
res1: List[Double] = List(2.0, 12.3)
Run Code Online (Sandbox Code Playgroud)