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])
但结果相同。
我有点困惑。你能解释一下我做错了什么吗?
由于类型擦除检查
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)