我正在学习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表示这是方法。
到底是什么?
答案 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中trait
和abstract 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.collection
中Traversable
的层次都是父级。
但是当你说
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}}会返回并中断循环
希望这对您有所帮助。