Визначення класів:
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
приймає функцію, яка має нульові параметри і повертає String.
(Майте на увазі, параметри пропускання імені збираються у функції; це просто робить синтаксис приємнішим.)
()
може бути відхилено у визначенні параметра функції, якщо функція бере лише один аргумент, наприклад:
def myOp2(passByNameString:(Int) => String) { .. } // - You can drop the ()
def myOp2(passByNameString:Int => String) { .. }
Але якщо для цього потрібно більше ніж один аргумент, ви повинні включити ():
def myOp2(passByNameString:(Int, String) => String) { .. }
Виписки:
.
можна скинути, щоб використовувати позначення операторів, які можуть бути використані лише для операторів infix (операторів методів, які беруть аргументи). Див . Відповідь Даниїла для отримання додаткової інформації.
.
також можна скинути для списку функцій постфіксу
()
може бути скинуто для операторів Postfix операторів list.tail
()
не можна використовувати з методами, визначеними як:
def aMethod = "hi!" // Missing () on method definition
aMethod // Works
aMethod() // Compile error when calling method
Оскільки це позначення зарезервовано за умовами для методів, які не мають побічних ефектів, як, наприклад, список № хвоста (тобто викликання функції без побічних ефектів означає, що функція не має спостережуваного ефекту, за винятком її зворотного значення).
()
може бути відхилено для позначення оператора при передачі в одному аргументі
()
може знадобитися використання операторів Postfix, які не знаходяться в кінці заяви
()
може знадобитися позначення вкладених операторів, кінців анонімних функцій або для операторів, які приймають більше одного параметра
Під час виклику функції, яка приймає функцію, ви не можете опустити () з внутрішнього визначення функції, наприклад:
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
IMO, надмірне використання типів повернення, що випадають, може бути шкідливим для повторного використання коду. Просто подивіться на специфікацію для гарного прикладу зниження читабельності через відсутність чіткої інформації в коді. Кількість рівнів непрямості, щоб фактично з'ясувати, який тип змінної може бути горіхами. Сподіваємось, кращі інструменти можуть запобігти цій проблемі та зберегти наш код стислим.
(Гаразд, у прагненні зібрати більш повну, стислу відповідь (якщо я щось пропустив чи щось невірно / неточно прокоментуйте), я додав до початку відповіді. Зверніть увагу, це не мова специфікація, тому я не намагаюсь зробити його точно академічно правильним - так само, як довідкова картка.)