2015-01-24 3 views
0

В Laziness разделе «Эффективное Scala», он говорит:Что означает «поля и методы эквивалентны»?

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])

Что значит «поле» и, эквивалентное «методы»? Разве это не довольно сильное заявление?

ответ

1

Ну, это просто означает, что вы можете определить реферат valdef и аннотация 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 
} 

Устойчивость

Вы можете задаться вопросом, что произойдет, если вы переопределить abstract 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() 

лени

Когда дело доходит до лени это единообразное поведение (лечащий поля и методы таким же образом) очень полезно.

Прежде всего обратите внимание, что абстрактное значение не существует, то есть вы не можете определить абстрактный val как lazy.

Реализация абстрактного deflazy val, с другой стороны, является совершенно законной и полезной. Значение lazy будет вычисляться только по первому вызову и сохранено в памяти (кэшировано и используется для будущих вызовов).

+0

Я всегда получаю ошибку «метод должен быть стабильным, неизменным значением», когда я переопределяю val с def. –

+0

Вы уверены, что это не когда вы переопределяете 'val' с' lazy val'? –

+0

Нет, я копирую ваш пример кода. –

0

Основная причина может заключаться в том, что lazy val и def вычисляются до их использования (а не при первом определении).

Разница заключается в том, что lazy val пытается избежать переоценки неизменяемого значения, которое добавило стоимость хранения вычисленного значения в памяти.