Что это значит, когда я использую def для определения поля в Scala?

Какова разница между:

scala> def foo = 5
foo: Int

и

scala> def foo() = 5
foo: ()Int

Кажется, что в обоих случаях В итоге я получаю переменную foo , на которую могу ссылаться без скобок, всегда получая значение 5 .

7
задан lindelof 16 August 2010 в 14:53
поделиться

4 ответа

В любом случае вы не определяете переменную. Вы определяете метод. Первый метод не имеет списков параметров, второй имеет один пустой список параметров. Первый из них должен быть вызывается так

val x = foo 

, а второй должен вызываться так

val x = foo()

. Однако компилятор Scala позволит вам вызывать методы с одним пустым списком параметров без скобок, поэтому для второго метода будет работать любая форма вызова. Методы без списков параметров не могут быть вызваны с круглыми скобками

. Предпочтительный стиль Scala состоит в том, чтобы определять и вызывать методы без аргументов, которые имеют побочные эффекты в круглых скобках. Методы без аргументов без побочных эффектов следует определять и вызывать без скобок.

Если вы на самом деле определяете переменную, синтаксис следующий:

val foo = 5
17
ответ дан 6 December 2019 в 05:54
поделиться

Прежде чем что-либо сказать, def не определяет поле, а определяет метод.

Во втором случае вы можете опустить круглые скобки из-за специфической особенности Scala. Здесь есть два интересных отличия: механическое и рекомендуемое использование.

Начиная с последнего, рекомендуется использовать пустой список параметров при наличии побочных эффектов. Классический пример - close () . Вы должны опустить круглые скобки, если нет побочных эффектов при вызове элемента.

Теперь, в качестве практического различия - помимо возможных странных синтаксических ошибок в угловых случаях (я не говорю, что они есть, просто предполагаю) - структурные типы должны следовать правильному соглашению.

Например, Источник содержит метод close без скобок, что означает структурный тип def close (): модуль не принимает Источник .Аналогично, если я определю структурный метод как def close: Unit , то объекты Java closeable не будут приняты.

6
ответ дан 6 December 2019 в 05:54
поделиться

В дополнение к уже приведенным ответам я хотел бы подчеркнуть два момента:

  • Возможность определять методы без списка параметров - это способ реализовать Единый принцип доступа . Это позволяет скрыть разницу между полями и методами, что упрощает последующие изменения реализации.

  • Вы можете вызвать метод, определенный как def foo () = 5 , используя foo , но вы не можете вызвать метод, определенный как def foo = 5 с использованием foo ()

4
ответ дан 6 December 2019 в 05:54
поделиться

Что это значит, когда я использую def для определения поля в Scala

Вы не можете определить поле, используя def .

Похоже, что в обоих случаях я получаю переменную foo, на которую я могу ссылаться без скобок, всегда равной 5.

Нет, в обоих случаях вы получаете метод foo , который можно вызывать без скобок.

Чтобы увидеть это, вы можете использовать javap :

// Main.scala
object Main {
  def foo1 = 5
  def foo2() = 5
}


F:\MyProgramming\raw>scalac main.scala

F:\MyProgramming\raw>javap Main
Compiled from "main.scala"
public final class Main extends java.lang.Object{
    public static final int foo2();
    public static final int foo1();
}

Однако см. http://tommy.chheng.com/index.php / 2010/03 / when-to-call-methods-with-or-without-parentheses-in-scala /

4
ответ дан 6 December 2019 в 05:54
поделиться
Другие вопросы по тегам:

Похожие вопросы: