Зачем использовать def и val в Scala или наоборот
Я знаю, что это обсуждалось на SO в других сообщениях раньше, и я понимаю основную разницу между использованием def
и val
. def
используется для определения метода и val
для неизменяемой ссылки. То, что я пытаюсь выполнить, задавая этот вопрос, заключается в том, чтобы понять, есть ли что-то большее для def
. Может ли он использоваться взаимозаменяемо с val
?
Недавно я попробовал следующий код и не могу убедить себя, достаточно ли моего нынешнего понимания def
:
scala> def i: Int = 3
i: Int
scala> i
res2: Int = 3
Итак, мне интересно, это эквивалентно val i = 3
?
Затем я попробовал это:
scala> i()
<console>:9: error: Int does not take parameters
i()
Я сделал это, чтобы проверить свое понимание семантики def
. Теперь я хочу знать, когда i
является методом, почему Scala жалуется на "... не принимает параметры"?
Далее я попробовал следующее:
scala> def i(): Int = 3
i: ()Int
scala> i()
res4: Int = 3
На этот раз Scala, похоже, согласен, что i
является методом. Могу ли я использовать def
вместо val
взаимозаменяемого для объявления и инициализации переменной?
Ответы
Ответ 1
И
def i = 3
и
def i() = 3
объявить методы. Единственное отличие состоит в том, что первый - это метод без списка параметров, а второй - метод с пустым списком параметров. Первый обычно используется для методов без побочных эффектов, а второй для методов с побочными эффектами.
Вы должны использовать val вместо def, если значение никогда не изменяется, и вы хотите избежать его пересчета. Def получает recomputed каждый раз, когда он вызывается, в то время как val присваивается значение только один раз.
Ответ 2
def
определяет метод, val
определяет неизменяемое значение, как вы уже знаете.
Одно существенное отличие заключается в том, что вычисляется выражение в правой части =
. Для метода он оценивается каждый раз, когда вы вызываете метод. Для значения это оценивается при инициализации значения. См. Разницу:
scala> def i: Int = { println("Hello"); 3 }
i: Int
scala> i
Hello
res0: Int = 3
scala> i
Hello
res1: Int = 3
scala> val i: Int = { println("Hello"); 3 }
Hello
i: Int = 3
scala> i
res2: Int = 3
Ответ 3
Чтобы добавить в верхней части ответа Кима, вы можете переопределить def по val.
// Entering paste mode (ctrl-D to finish)
trait A {
def i: Int
def num: Long
}
class B extends A {
val i = 7
val num = 20L
}
// Exiting paste mode, now interpreting.
defined trait A
defined class B
scala> val b = new B
b: B = [email protected]
scala> b.i
res1: Int = 7
scala> b.num
res2: Long = 20