Définitions de classe:
val
ou var
peut être omis des paramètres de classe, ce qui rendra le paramètre privé.
L'ajout de var ou val le rendra public (c'est-à-dire que des accesseurs de méthode et des mutateurs sont générés).
{}
peut être omis si la classe n'a pas de corps, c'est-à-dire
class EmptyClass
Instanciation de classe:
Les paramètres génériques peuvent être omis s'ils peuvent être déduits par le compilateur. Cependant, notez que si vos types ne correspondent pas, alors le paramètre de type est toujours déduit pour qu'il corresponde. Donc, sans spécifier le type, vous n'obtiendrez peut-être pas ce que vous attendez - c'est-à-dire étant donné
class D[T](val x:T, val y:T);
Cela vous donnera une erreur de type (Int trouvé, chaîne attendue)
var zz = new D[String]("Hi1", 1) // type error
Alors que cela fonctionne bien:
var z = new D("Hi1", 1)
== D{def x: Any; def y: Any}
Parce que le paramètre de type, T, est inféré comme le supertype le moins commun des deux - Any.
Définitions des fonctions:
=
peut être supprimée si la fonction renvoie Unit (rien).
{}
car le corps de la fonction peut être supprimé si la fonction est une seule instruction, mais uniquement si l'instruction renvoie une valeur (vous avez besoin du =
signe), c'est-à-dire
def returnAString = "Hi!"
mais cela ne fonctionne pas:
def returnAString "Hi!" // Compile error - '=' expected but string literal found."
Le type de retour de la fonction peut être omis s'il peut être déduit (une méthode récursive doit avoir son type de retour spécifié).
()
peut être abandonné si la fonction ne prend aucun argument, c'est-à-dire
def endOfString {
return "myDog".substring(2,1)
}
qui par convention est réservé aux méthodes qui n'ont pas d'effets secondaires - nous en parlerons plus tard.
()
n'est pas réellement abandonné en soi lors de la définition d'un paramètre de passage par nom , mais il s'agit en fait d'une notation assez sémantiquement différente, c'est-à-dire
def myOp(passByNameString: => String)
Dit que myOp prend un paramètre pass-by-name, qui aboutit à une chaîne (c'est-à-dire qu'il peut s'agir d'un bloc de code qui renvoie une chaîne) par opposition aux paramètres de fonction,
def myOp(functionParam: () => String)
qui dit myOp
prend une fonction qui n'a aucun paramètre et renvoie une chaîne.
(Remarquez que les paramètres de passage par nom sont compilés en fonctions; cela rend simplement la syntaxe plus agréable.)
()
peut être supprimée dans la définition du paramètre de fonction si la fonction ne prend qu'un seul argument, par exemple:
def myOp2(passByNameString:(Int) => String) { .. } // - You can drop the ()
def myOp2(passByNameString:Int => String) { .. }
Mais si cela prend plus d'un argument, vous devez inclure le ():
def myOp2(passByNameString:(Int, String) => String) { .. }
Déclarations:
.
peuvent être supprimés pour utiliser la notation d'opérateur, qui ne peut être utilisée que pour les opérateurs d'infixe (opérateurs de méthodes qui prennent des arguments). Voir la réponse de Daniel pour plus d'informations.
.
peut également être supprimé pour les fonctions postfix list tail
()
peut être supprimé pour les opérateurs postfix list.tail
()
ne peut pas être utilisé avec les méthodes définies comme:
def aMethod = "hi!" // Missing () on method definition
aMethod // Works
aMethod() // Compile error when calling method
Parce que cette notation est réservée par convention pour les méthodes qui n'ont pas d'effets secondaires, comme List # tail (c'est-à-dire que l'invocation d'une fonction sans effets secondaires signifie que la fonction n'a aucun effet observable, à l'exception de sa valeur de retour).
()
peut être supprimé pour la notation d'opérateur lors de la transmission d'un seul argument
()
peut être nécessaire d'utiliser des opérateurs postfix qui ne sont pas à la fin d'une instruction
()
peut être nécessaire pour désigner des instructions imbriquées, des fins de fonctions anonymes ou pour des opérateurs qui prennent plus d'un paramètre
Lorsque vous appelez une fonction qui prend une fonction, vous ne pouvez pas omettre le () de la définition de fonction interne, par exemple:
def myOp3(paramFunc0:() => String) {
println(paramFunc0)
}
myOp3(() => "myop3") // Works
myOp3(=> "myop3") // Doesn't work
Lorsque vous appelez une fonction qui prend un paramètre par nom, vous ne pouvez pas spécifier l'argument en tant que fonction anonyme sans paramètre. Par exemple, étant donné:
def myOp2(passByNameString:Int => String) {
println(passByNameString)
}
Vous devez l'appeler comme suit:
myOp("myop3")
ou
myOp({
val source = sourceProvider.source
val p = myObject.findNameFromSource(source)
p
})
mais non:
myOp(() => "myop3") // Doesn't work
OMI, la surutilisation de la suppression des types de retour peut être préjudiciable à la réutilisation du code. Il suffit de regarder les spécifications pour un bon exemple de lisibilité réduite en raison du manque d'informations explicites dans le code. Le nombre de niveaux d'indirection pour déterminer réellement quel est le type d'une variable peut être fou. Espérons que de meilleurs outils peuvent éviter ce problème et garder notre code concis.
(OK, dans le but de compiler une réponse plus complète et concise (si j'ai manqué quelque chose, ou quelque chose de mal / inexact, veuillez commenter), j'ai ajouté au début de la réponse. Veuillez noter que ce n'est pas une langue spécification, donc je n'essaye pas de la rendre exactement correcte sur le plan académique - mais plutôt comme une carte de référence.)