Klassendefinitionen:
val
oder var
kann in Klassenparametern weggelassen werden, wodurch der Parameter privat wird.
Durch Hinzufügen von var oder val wird es öffentlich (dh es werden Methodenzugriffsmethoden und Mutatoren generiert).
{}
kann weggelassen werden, wenn die Klasse keinen Körper hat, d. h.
class EmptyClass
Klasseninstanziierung:
Generische Parameter können weggelassen werden, wenn sie vom Compiler abgeleitet werden können. Beachten Sie jedoch, dass der Typparameter immer abgeleitet wird, wenn Ihre Typen nicht übereinstimmen. Ohne Angabe des Typs erhalten Sie möglicherweise nicht das, was Sie erwarten - das heißt, gegeben
class D[T](val x:T, val y:T);
Dies gibt Ihnen einen Typfehler (Int gefunden, erwartete Zeichenfolge)
var zz = new D[String]("Hi1", 1) // type error
Während dies gut funktioniert:
var z = new D("Hi1", 1)
== D{def x: Any; def y: Any}
Weil der Typparameter T als der am wenigsten verbreitete Supertyp der beiden abgeleitet wird - Any.
Funktionsdefinitionen:
=
kann gelöscht werden, wenn die Funktion Unit (nichts) zurückgibt.
{}
Denn der Funktionskörper kann gelöscht werden, wenn die Funktion eine einzelne Anweisung ist, aber nur, wenn die Anweisung einen Wert zurückgibt (Sie benötigen das =
Vorzeichen), d. h.
def returnAString = "Hi!"
aber das funktioniert nicht:
def returnAString "Hi!" // Compile error - '=' expected but string literal found."
Der Rückgabetyp der Funktion kann weggelassen werden, wenn er abgeleitet werden kann (für eine rekursive Methode muss der Rückgabetyp angegeben werden).
()
kann gelöscht werden, wenn die Funktion keine Argumente akzeptiert, d. h.
def endOfString {
return "myDog".substring(2,1)
}
was konventionell Methoden vorbehalten ist, die keine Nebenwirkungen haben - dazu später mehr.
()
wird bei der Definition eines Pass-by-Name- Parameters nicht per se gelöscht , aber es handelt sich tatsächlich um eine ganz semantisch andere Notation, d. h.
def myOp(passByNameString: => String)
MyOp verwendet einen Parameter für die Namensübergabe, der im Gegensatz zu Funktionsparametern zu einem String führt (dh es kann sich um einen Codeblock handeln, der einen String zurückgibt).
def myOp(functionParam: () => String)
Das heißt, myOp
nimmt eine Funktion, die keine Parameter hat, und gibt einen String zurück.
(Wohlgemerkt, Pass-by-Name-Parameter werden in Funktionen kompiliert; dies macht die Syntax nur schöner.)
()
kann in der Funktionsparameterdefinition gelöscht werden, wenn die Funktion nur ein Argument akzeptiert, zum Beispiel:
def myOp2(passByNameString:(Int) => String) { .. } // - You can drop the ()
def myOp2(passByNameString:Int => String) { .. }
Wenn jedoch mehr als ein Argument erforderlich ist, müssen Sie das () einschließen:
def myOp2(passByNameString:(Int, String) => String) { .. }
Aussagen:
.
kann gelöscht werden, um die Operator-Notation zu verwenden, die nur für Infix-Operatoren (Operatoren von Methoden, die Argumente annehmen) verwendet werden kann. Weitere Informationen finden Sie in Daniels Antwort .
.
kann auch für die Liste der Postfix-Funktionen gelöscht werden
()
kann für Postfix-Operatoren list.tail gelöscht werden
()
kann nicht mit folgenden Methoden verwendet werden:
def aMethod = "hi!" // Missing () on method definition
aMethod // Works
aMethod() // Compile error when calling method
Da diese Notation gemäß der Konvention für Methoden reserviert ist, die keine Nebenwirkungen haben, wie z. B. List # tail (dh der Aufruf einer Funktion ohne Nebenwirkungen bedeutet, dass die Funktion außer ihrem Rückgabewert keine beobachtbaren Auswirkungen hat).
()
kann für die Operatornotation gelöscht werden, wenn ein einzelnes Argument übergeben wird
()
Möglicherweise müssen Postfix-Operatoren verwendet werden, die nicht am Ende einer Anweisung stehen
()
Möglicherweise müssen verschachtelte Anweisungen, Enden anonymer Funktionen oder Operatoren angegeben werden, die mehr als einen Parameter verwenden
Wenn Sie eine Funktion aufrufen, die eine Funktion übernimmt, können Sie das () in der inneren Funktionsdefinition nicht weglassen, zum Beispiel:
def myOp3(paramFunc0:() => String) {
println(paramFunc0)
}
myOp3(() => "myop3") // Works
myOp3(=> "myop3") // Doesn't work
Wenn Sie eine Funktion aufrufen, die einen By-Name-Parameter verwendet, können Sie das Argument nicht als parameterlose anonyme Funktion angeben. Zum Beispiel gegeben:
def myOp2(passByNameString:Int => String) {
println(passByNameString)
}
Sie müssen es nennen als:
myOp("myop3")
oder
myOp({
val source = sourceProvider.source
val p = myObject.findNameFromSource(source)
p
})
aber nicht:
myOp(() => "myop3") // Doesn't work
IMO kann eine übermäßige Verwendung von Drop-Return-Typen schädlich für die Wiederverwendung von Code sein. Schauen Sie sich einfach die Spezifikation an, um ein gutes Beispiel für eine eingeschränkte Lesbarkeit zu finden, da der Code keine expliziten Informationen enthält. Die Anzahl der Indirektionsebenen, um tatsächlich herauszufinden, um welchen Typ es sich bei einer Variablen handelt, kann verrückt sein. Hoffentlich können bessere Tools dieses Problem abwenden und unseren Code präzise halten.
(OK, um eine vollständigere, präzisere Antwort zu erstellen (wenn ich etwas verpasst habe oder etwas falsch / ungenau gemacht habe, bitte kommentieren Sie), habe ich am Anfang der Antwort hinzugefügt. Bitte beachten Sie, dass dies keine Sprache ist Spezifikation, also versuche ich nicht, es genau akademisch korrekt zu machen - nur eher wie eine Referenzkarte.)