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

В чем именно разница между:

scala> def foo = 5
foo: Int

и

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

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

Ответы [ 4 ]

17 голосов
/ 16 августа 2010

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

val x = foo 

, а второй - следующим образом

val x = foo()

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

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

Если вы действительно хотите определить переменную, синтаксис будет

val foo = 5
6 голосов
/ 16 августа 2010

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

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

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

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

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

4 голосов
/ 16 августа 2010

Что это значит, когда я использую 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/

3 голосов
/ 16 августа 2010

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...