什么"字段和方法是等价的"意思?

时间:2015-01-24 13:27:09

标签: scala methods field uap

在“有效Scala”的Laziness部分,它说:

  

当val以lazy为前缀时,scala中的字段由需要计算。因为字段和方法在Scala中是等效的(以免字段是私有的[this])

“字段”和“方法”的含义是什么意思?这不是一个相当强烈的声明吗?

3 个答案:

答案 0 :(得分:1)

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

例如

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
}

<强>稳定性

您可能想知道如果覆盖带有val的摘要def会发生什么情况,每次调用它时会给您一个不同的值。您是否会获得第一个计算值,因为该项目是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

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

答案 1 :(得分:1)

由于Uniform Access Principle

,字段和方法是等效的
  

模块提供的所有服务都应该通过统一的符号提供,不会背叛它们是通过存储还是通过计算来实现

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

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

答案 2 :(得分:0)

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

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