Определения классов:
val
или var
может быть опущено в параметрах класса, что сделает параметр закрытым.
Добавление var или val приведет к тому, что он станет общедоступным (то есть будут созданы методы доступа и мутаторы).
{}
может быть опущено, если у класса нет тела, то есть
class EmptyClass
Создание экземпляра класса:
Общие параметры можно не указывать, если они могут быть определены компилятором. Однако обратите внимание: если ваши типы не совпадают, параметр типа всегда передается, чтобы он соответствовал. Таким образом, без указания типа вы можете не получить то, что ожидаете, то есть с учетом
class D[T](val x:T, val y:T);
Это даст вам ошибку типа (найден Int, ожидаемая строка)
var zz = new D[String]("Hi1", 1) // type error
Тогда как это отлично работает:
var z = new D("Hi1", 1)
== D{def x: Any; def y: Any}
Поскольку параметр типа T определяется как наименее распространенный супертип из двух - Any.
Определения функций:
=
может быть отброшен, если функция возвращает Unit (ничего).
{}
для тела функции можно отбросить, если функция является одним оператором, но только если оператор возвращает значение (вам нужен =
знак), то есть
def returnAString = "Hi!"
но это не работает:
def returnAString "Hi!" // Compile error - '=' expected but string literal found."
Тип возвращаемого значения функции можно не указывать, если его можно вывести (рекурсивный метод должен иметь указанный тип возврата).
()
можно отбросить, если функция не принимает аргументов, то есть
def endOfString {
return "myDog".substring(2,1)
}
который по соглашению зарезервирован для методов, не имеющих побочных эффектов - подробнее об этом позже.
()
на самом деле не отбрасывается как таковой при определении параметра передачи по имени , но на самом деле это совершенно семантически другая нотация, то есть
def myOp(passByNameString: => String)
Говорит, что myOp принимает параметр передачи по имени, который приводит к строке (то есть это может быть блок кода, который возвращает строку), а не параметры функции,
def myOp(functionParam: () => String)
в котором говорится, что myOp
принимает функцию с нулевыми параметрами и возвращает строку.
(Имейте в виду, что параметры, передаваемые по имени, компилируются в функции; это просто улучшает синтаксис.)
()
может быть опущено в определении параметра функции, если функция принимает только один аргумент, например:
def myOp2(passByNameString:(Int) => String) { .. } // - You can drop the ()
def myOp2(passByNameString:Int => String) { .. }
Но если требуется более одного аргумента, вы должны включить ():
def myOp2(passByNameString:(Int, String) => String) { .. }
Заявления:
.
можно отбросить, чтобы использовать нотацию операторов, которая может использоваться только для инфиксных операторов (операторов методов, принимающих аргументы). См . Ответ Даниэля для получения дополнительной информации.
.
также может быть удалено для хвоста списка постфиксных функций
()
можно отбросить для постфиксных операторов list.tail
()
не может использоваться с методами, определенными как:
def aMethod = "hi!" // Missing () on method definition
aMethod // Works
aMethod() // Compile error when calling method
Поскольку эта нотация зарезервирована по соглашению для методов, которые не имеют побочных эффектов, таких как List # tail (то есть вызов функции без побочных эффектов означает, что функция не имеет наблюдаемого эффекта, за исключением ее возвращаемого значения).
()
можно опустить для обозначения оператора при передаче одного аргумента
()
может потребоваться использовать постфиксные операторы, которых нет в конце оператора
()
может потребоваться для обозначения вложенных операторов, концов анонимных функций или для операторов, которые принимают более одного параметра
При вызове функции, которая принимает функцию, вы не можете опустить () из определения внутренней функции, например:
def myOp3(paramFunc0:() => String) {
println(paramFunc0)
}
myOp3(() => "myop3") // Works
myOp3(=> "myop3") // Doesn't work
При вызове функции, которая принимает параметр по имени, вы не можете указать аргумент как анонимную функцию без параметров. Например, учитывая:
def myOp2(passByNameString:Int => String) {
println(passByNameString)
}
Вы должны называть это так:
myOp("myop3")
или
myOp({
val source = sourceProvider.source
val p = myObject.findNameFromSource(source)
p
})
но нет:
myOp(() => "myop3") // Doesn't work
ИМО, чрезмерное использование отбрасываемых типов возврата может быть вредным для повторного использования кода. Просто посмотрите на спецификацию, чтобы увидеть хороший пример снижения читабельности из-за отсутствия явной информации в коде. Количество уровней косвенного обращения к типу переменной может быть безумным. Надеюсь, более совершенные инструменты помогут избежать этой проблемы и сделать наш код лаконичным.
(Хорошо, в стремлении составить более полный, краткий ответ (если я что-то пропустил или получил что-то не так / неточно, прокомментируйте), я добавил в начало ответа. Обратите внимание, что это не язык спецификации, поэтому я не пытаюсь сделать ее строго академически правильной - просто больше похоже на справочную карту.)