标头字段值或方法在Scala中吗?

时间:2018-11-26 12:59:33

标签: scala

我正在学习Scala。

我很困惑Scala不可变列表中的方法或字段值是头。

列表声明在下面。

sealed abstract class List[+A] extends .... {
  def isEmpty: Boolean
  def head: A //I think it is field value not a function or method
  def tail: List[A]

但是intelliJ表示这是方法。

到底是什么?

3 个答案:

答案 0 :(得分:6)

List是一个抽象类,def head这里是一个抽象方法,因此声明和IJ都是正确的。

在列表的非空实例::中,其实现方式如下:

final case class ::[B](override val head: B, private[scala] var tl: List[B]) extends List[B] {
  override def tail : List[B] = tl
  override def isEmpty: Boolean = false
}

因此, field head用于实现抽象方法 head。这在Scala中是合法的:val和无参数def之间没有太大区别,您可以以二进制兼容的方式在一个和另一个之间进行切换。

在列表Nil的空实例中,实现此方法以引发异常:

case object Nil extends List[Nothing] {
  override def head: Nothing =
    throw new NoSuchElementException("head of empty list")
/*...*/
}

字段不能“引发异常”,但是方法显然可以。

答案 1 :(得分:4)

这是Scala中traitabstract class一起使用的常见模式:子类中的val s可以覆盖字段:

scala> trait A { def foo: String }
defined trait A

scala> class B(val foo: String) extends A
defined class B

scala> new B("hello").foo
res0: String = hello

因此答案是针对非抛出的具体实现,它将是val,并且不会在调用堆栈中放入任何内容(请参见here);对于抽象实现或抛出具体实现,它将为def

答案 2 :(得分:2)

众所周知,所有高级抽象类或特征scala.collectionTraversable的层次都是父级。 但是当你说

   def head: A //I think it is field value not a function or method

我会说head不是字段值,而是方法。 如果您使用TraversableLike特性,则会发现以下实现。

    /** Selects the first element of this $coll.
    *  $orderDependent
    *  @return  the first element of this $coll.
    *  @throws NoSuchElementException if the $coll is empty.
    */
    def head: A = {
    var result: () => A = () => throw new NoSuchElementException
    breakable {
    for (x <- this) {
     result = () => x
     break
     }
    }
    result()
    }

因此,它采用集合类型List[A]并检查该元素是否为空,然后引发异常,否则将成为x的{​​{1}}会返回并中断循环

希望这对您有所帮助。