我能使用视图界定(view bound)在Scala值类中吗?

4

在处理一些Java代码时,我想找到一种方法来缩小原始集合并包含其参数化类型。

我也希望它能够适用于Scala集合,所以我做了以下操作:

implicit class Harden[S <% mutable.Set[_]](val set: S) extends AnyVal {
    def cast[T] = set.map(_.asInstanceOf[T])
}

那导致了一个编译器错误,这个错误我没想到。
Error:(27, 27) field definition is not allowed in value class
  implicit class Harden[S <% mutable.Set[_]](val set: S) extends AnyVal {

在Scala视图界限或值类文档中,我没有找到任何提及此类型限制的内容。

为什么这是不被允许的?我正在使用Scala 2.10.3。


1
我认为视图绑定(<%)将在2.12中被弃用。只是让你知道。 - Ryoichiro Oka
2个回答

5

从这个 sbt console 输出中可以看出:

scala> :type implicit class Harden[S <% mutable.Set[_]](val set: S)
[S]AnyRef {
  val set: S
  private[this] val set: S
  implicit private[this] val evidence$1: S => scala.collection.mutable.Set[_]
  def <init>(set: S)(implicit evidence$1: S => scala.collection.mutable.Set[_]): Harden[S]
}

实际上,Harden 的构造函数在幕后被解析为:

def <init>(set: S)(implicit evidence$1: S => scala.collection.mutable.Set[_]): Harden[S]

如在 value classes limitations 中所述:

必须只有一个主构造函数,该构造函数恰好有一个公共的 val 参数,其类型不是一个值类。

这意味着 Harden 违反了此限制。

但是您可以实现类似的功能。尝试将类上定义的视图界定转换为方法中的隐式证明。

类似于下面这样:

scala> implicit class Harden[S](val set: S) extends AnyVal {
     |     def cast[T](implicit ev: S => scala.collection.mutable.Set[_]) = set.map(_.asInstanceOf[T])
     | }
defined class Harden

这将编译通过:
scala> Set(1,2,3).cast[Any]
res17: scala.collection.mutable.Set[Any] = Set(1, 2, 3)

这将会失败,正如预期的一样:

scala> List(1,2,3).cast[Any]
<console>:24: error: No implicit view available from List[Int] => scala.collection.mutable.Set[_].
              List(1,2,3).cast[Any]
                              ^

4

这是不被允许的,因为按照当前的结构,值类必须只有一个参数,但是

implicit class Foo[A <% B](val a: A)

转换成

implicit class Foo[A,B](val a: A)(implicit evidence$1: A => B)

现在,它不再只有单个参数。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接