Scala-методы без аргументов

В Scala есть два способа определить метод без аргументов.

    1 def a=println("hello")

    2 def a()=println("hello")

Эти два метода совершенно одинаковы, но (2) можно вызывать как с круглыми скобками, так и без них.

Есть ли какая-то особая причина, по которой эта функция разрешена в Scala. Меня смущает, что и когда использовать?


person codecool    schedule 04.08.2011    source источник
comment
Чтобы не запутать вас еще больше, попробуйте def a()()=println("hello")....   -  person Rex Kerr    schedule 04.08.2011
comment
Это методы, а не функции.   -  person Daniel C. Sobral    schedule 04.08.2011


Ответы (3)


Общее правило заключается в том, что вы должны добавлять пустой список параметров как на сайт объявления, так и на сайт вызова всякий раз, когда метод (не функция) имеет побочные эффекты.

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

person Jean-Philippe Pellet    schedule 04.08.2011
comment
Функции побочного эффекта — это те, которые ничего не возвращают и выполняют некоторый ввод-вывод или изменяют состояние. Я прав? Как насчет функции, которая выполняет ввод-вывод, изменяет состояние и все еще что-то возвращает? - person codecool; 04.08.2011
comment
Возвращает ли он что-то, не имеет значения. - person Alexey Romanov; 04.08.2011
comment
Цель соглашения состоит в том, что пустой список параметров предупреждает пользователя о том, что в результате вызова метода возникает некоторый побочный эффект, независимо от возвращаемого значения. - person Kipton Barros; 04.08.2011
comment
@codecool, функции побочных эффектов - это те подпрограммы, которые изменяют внутреннее состояние. Слово «побочный эффект» может ввести в заблуждение без надлежащего контекста. Иногда это то, чего вы хотите и ожидаете. - person Victor; 09.06.2016

Допускается синтаксис без скобок, поэтому можно написать так:

abstract class X {
  def f: Int
}

class Y extends X {
  val f = 0
}

Код, вызывающий f на X, не должен знать, является ли это val или def.

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

Как уже было сказано, существует соглашение об использовании пустого списка параметров, когда метод имеет побочные эффекты, и отказ от них в противном случае.

person Daniel C. Sobral    schedule 04.08.2011
comment
можете ли вы объяснить, почему вы описали def в вопросе как методы, а не функции? Нельзя ли def превратить в функции, если передать их в функцию более высокого порядка? или присвоено типу функции Unit => Unit? - person Toby; 10.09.2017
comment
@Toby Функции и методы - разные вещи, и здесь я говорю о методах. - person Daniel C. Sobral; 15.09.2017

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

Кстати, если вы объявляете чисто побочный метод, используя =, вам, вероятно, следует явно объявить возвращаемый тип Unit, например:

def a: Unit = println("hello")

Обратите внимание, что любой тип можно привести к Unit.

Если вы не хотите явно объявлять тип возвращаемого значения, вам, вероятно, следует опустить =. Тогда компилятор выведет возвращаемый тип Unit, даже если последнее выражение возвращает что-то другое:

def a() { println("hello") }

Оба вышеупомянутых стиля делают рефакторинг более безопасным, поскольку изменение тела метода никогда не приведет к тому, что компилятор выведет другой тип возвращаемого значения. IMO, эта явность объявления более важна, чем стиль кода сайта вызова.

person Ben James    schedule 04.08.2011