"fields and methods are equivalent" 是什么意思?

What does "fields and methods are equivalent" mean?

在 'Effective Scala' 的 Laziness 部分,它说:

Fields in scala are computed by need when val is prefixed with lazy. Because fields and methods are equivalent in Scala (lest the fields are private[this])

'fields'和'methods'等价是什么意思?是不是比较强硬的说法?

主要原因可能是,lazy valdef 在使用之前计算(而不是在首次定义时)。

不同之处在于 lazy val 试图避免重新评估不变的值,这增加了将计算值保存在内存中的成本。

嗯,这只是意味着您可以通过 def 定义抽象 val,通过 val 定义抽象 def

例如

trait Server {
  def port:Int
}

有一个抽象函数,即port。您肯定可以使用 def 实现(或定义或覆盖)它,例如

object DefaultServer extends Server {
  override def port: Int = 80
}

但在这种情况下,每次访问 port 都会导致根本不需要的函数应用程序(或方法调用)。出于这个简单的原因,Scala 为我们提供了使用值

实现抽象 def 的可能性
object DefaultServer extends Server {
  override val port: Int = 80
}

这同样适用于抽象值。您可以使用相同的语法定义抽象值:

trait Server {
  val port: Int
}

您可以使用 def:

覆盖它们
object DefaultServer extends Server {
  override def port: Int = 80
}

稳定性

您可能想知道如果您用每次调用时给您不同值的 def 覆盖抽象 val 会发生什么。您会因为该项目是 val 而获得第一个计算值,还是每次调用它都会获得不同的值,因为实际实现是 def.

例如:

object DefaultServer extends Server {
  override def port: Int = scala.util.Random.nextInt()
}

幸运的是 Scala 编译器检测到这一点并抛出以下错误:

error: overriding value a in trait Server of type Int;
method a needs to be a stable, immutable value
   override def port:Int = scala.util.Random.nextInt()

懒惰

当谈到懒惰时,这种统一的行为(以相同的方式处理字段和方法)非常有用。

首先注意 lazy 抽象值不存在,即你不能将抽象 val 定义为 lazy.

另一方面,通过 lazy val 实现抽象 def 是完全合法且有用的。 lazy 值将仅在第一次调用时计算并记忆(缓存并用于以后的调用)。

由于 Uniform Access Principle:

,字段和方法是等价的

All services offered by a module should be available through a uniform notation, which does not betray whether they are implemented through storage or through computation

在 Scala 中查看有关 how it's implemented 的更多信息。

P.S。 Scala 中的 UAP 似乎是 not completely implemented