Scala Product、case类和元组

Product、case类和元组

case 关键字不仅可以推断出val,同时自动增加一些方法,那么增加了那些方法呢?

你定义的case 类会混入scala.Product 特征,它提供了几个关于实例字段的通用方法。例如,对于Person 的实例:

package cn.com.tengen.test.obj
case class Person(name: String,age: Option[Int] = None)

object Person extends App{
  val p = Person("Lucky",Option(18))
  println(p.productArity) //元素的个数            输出:2
  println(p.productElement(0))//第1个元素         输出:Lucky
  println(p.productElement(1))//第二个元素        输出:Some(18)
  p.productIterator foreach println//便利         输出:Lucky  Some(18)
}

Product 源码:

package scala
trait Product extends scala.Any with scala.Equals {
  def productElement(n : scala.Int) : scala.Any
  def productArity : scala.Int
  def productIterator : scala.Iterator[scala.Any] = { /* compiled code */ }
  def productPrefix : java.lang.String = { /* compiled code */ }
}

尽管以通用方法访问字段非常有用,但由于对各个字段使用的是Any 类型,而不是其具体类型,这种机制的作用受到了局限。

对于不同的字段数量, 也有Product 的子类型最大值为22。这些类型为特定的字段添加了一些方法,可以保持该字段的正确类型信息。例如:

 Product2源码:

package scala
trait Product2[@scala.specialized +T1, @scala.specialized +T2] extends scala.Any with scala.Product {
  override def productArity : scala.Int = { /* compiled code */ }
  @scala.throws[scala.IndexOutOfBoundsException](classOf[scala.IndexOutOfBoundsException])
  override def productElement(n : scala.Int) : scala.Any = { /* compiled code */ }
  def _1 : T1
  def _2 : T2
}
object Product2 extends scala.AnyRef {
  def unapply[T1, T2](x : scala.Product2[T1, T2]) : scala.Option[scala.Product2[T1, T2]] = { /* compiled code */ }
}

这些方法返回了字段的真正类型。这里的类型参数是协变的,因为ProductN 特征只用于不可变的类型。用类似_1 的方法访问这些字段需要使用对应的类型参数T1,T1 处在协变的位置(即返回值类型)。

这些方法与用来访问元组元素的方法是相同的。事实上,所有的TupleN 类型都继承了对应的ProductN 特征,并提供了_1 到_N 方法的具体实现,N 最大可为22:


object Test {
  def main(args: Array[String]): Unit = {
    val t1 = ("Lucky", 26)
    println(t1)//输出: (Lucky,26)
    println(t1._1)//输出: Lucky
    println(t1._2)//输出: 26
  }
}

为什么个数的上限是22 ?这个数字的选择有些随意,但你可以合理地认为元组中有22 个元素无论如何都已经足够多了。

这对于人类来说确实如此,但不幸的是,存在一个常见的情景需要超出这个数量限制:保存大的数据“记录”中的字段(或列)。对于SQL 或NoSQL 数据集,包含超过22 个元素的情况并非罕见。元组很有用,至少对于小数据的确如此,因为元组可以保持字段(列)的顺序和类型。所以,22 个元素的限制是一个问题。

事实证明,在Scala 2.10 中,case 类也受到不超过22 个字段的限制。但这个实现上的限制在2.11 版本中取消了,所以数据应用可以为超过22 个元素的数据记录使用case 类。

扫描二维码关注公众号,回复: 4149482 查看本文章

猜你喜欢

转载自blog.csdn.net/u014646662/article/details/84100854
今日推荐