我实现了一个自定义集合类,它基本上是一个具有隐式整数键和值的Map
,这些键和值是AnyRef
的子类。它使用Int
键作为底层数组结构的索引。这是类声明签名(类实例化是在伴随对象中完成的,因此是私有构造函数(:
class ArrayMap[T >: Null <: AnyRef: ClassTag] private (private var data: Array[T]) { self =>
...
}
现在我想添加所需的理解方法。我定义了两个不同的映射函数。一个返回List
,另一个返回相同的数据类型(ArrayMap
(。
def map[X](f: (Int, T) => X): List[X] = { ... }
def map[X >: Null <: AnyRef: ClassTag](f: (Int, T) => X): ArrayMap[X] = { ... }
def foreach(f: (Int, T) => Unit): Unit = { ... }
def flatMap[X >: Null <: AnyRef: ClassTag](f: (Int, T) => Iterable[(Int, X)]): ArrayMap[X] = { ... }
def filter(p: (Int, T) => Boolean): ArrayMap[T] = { ... }
没有定义隐式。单独使用时,上述功能可按预期工作。这个问题有待理解。For循环要么选择返回List
的第一个map
,要么抛出一个神秘错误。以下示例产生错误:
val map = ArrayMap.empty[Integer]
map(0) = 0
map(1) = 1
map(5) = 2
map(6) = 3
map(10) = 4
val rs: ArrayMap[String] = for (e <- map) yield e._2.toString
以上代码抛出:
Error:(293, 41) missing parameter type
val rs: ArrayMap[String] = for (e <- map) yield e._2.toString
我错过了什么?
[更新]
这里提供了完整的实现要点。
问题与类型不匹配有关,您将传递给map
的函数定义为两个参数的函数(Int
&T
(到X
。而在你的理解中,你将其视为一个参数(元组(Int, T)
(到X
的函数。
最简单的解决方案是重新定义map
函数签名例如
import scala.reflect.ClassTag
class ArrayMap[T >: Null <: AnyRef: ClassTag] (val data: Array[T]) {
// Note the double parenthesis (()).
def map[X >: Null <: AnyRef: ClassTag](f: ((Int, T)) => X): ArrayMap[X] = ???
def withFilter(p: ((Int, T)) => Boolean): ArrayMap[T] = ???
}
有了这个定义,你可以制作类似的东西
val map: ArrayMap[java.lang.Integer] = new ArrayMap(Array(1, 2, 3))
// Note I use lazy val to avoid the NotImplementedException.
lazy val rs1: ArrayMap[String] = map.map(tuple => tuple._2.toString)
lazy val rs2: ArrayMap[String] = map.map { case (_, v) => v.toString }
lazy val rs3: ArrayMap[String] = for {
tuple <- map
} yield tuple._2.toString
lazy val rs4: ArrayMap[String] = for {
(_, v) <- map
} yield v.toString
请参阅ScalaMap中map
的完整签名作为参考。