如何为Scala中的任何集合创建通用隐式类?

ov7*_*v7a 2 generics collections scala implicit-conversion

我想编写一个方法,None如果集合为空,则返回该方法Some(collection).

我能得到的最好的是

implicit class CollectionExtensions[A, Repr](self: TraversableLike[A, Repr]){
  def toOption: Option[Repr] = if (self.nonEmpty) Some(self.asInstanceOf[Repr]) else None
}
Run Code Online (Sandbox Code Playgroud)

但铸造.asInstanceOf[Repr]似乎是错误的.什么是正确的方法?

Kol*_*mar 5

除了@ dk14答案之外,您还可以使用以下其他一些方法:

  • 使用隐式类Repr with TraversableOnce[A].这也将支持Iterator,因为Iterator扩展TraversableOnce,但不是TraversableLike.

    implicit class CollectionExtensions[A, Repr](val self: Repr with TraversableOnce[A]) extends AnyVal {
      def toOption: Option[Repr] = if (self.nonEmpty) Some(self) else None
    }
    
    Run Code Online (Sandbox Code Playgroud)
  • 仅使用隐式类Repr,但请求可隐式转换为的证据Traversable.这种方法也支持Arrays和Strings,因为它们根本不扩展Traversable,但可以隐式转换为它.

    implicit class CollectionExtensions[Repr](val self: Repr) extends AnyVal {
      def toOption[A](implicit ev: Repr => TraversableOnce[A]): Option[Repr] = {
        val traversable = ev(self)
        if (traversable.isEmpty) None else Some(self)
      }
    }
    
    Run Code Online (Sandbox Code Playgroud)

这两种方法都保留了原始类型:

scala> List(1, 2, 3).toOption
res1: Option[List[Int]] = Some(List(1, 2, 3))

scala> Iterator(1, 2, 3).toOption
res2: Option[Iterator[Int]] = Some(non-empty iterator)

scala> Array.empty[Int].toOption
res3: Option[Array[Int]] = None

scala> Map(1 -> 2).toOption
res4: Option[scala.collection.immutable.Map[Int,Int]] = Some(Map(1 -> 2))

scala> "123".toOption
res5: Option[String] = Some(123)

scala> "".toOption
res6: Option[String] = None
Run Code Online (Sandbox Code Playgroud)