Bevor ich Scala lernte, habe ich für die tägliche Entwicklungsarbeit hauptsächlich Java und Python verwendet. Meinem Eindruck nach habe ich nicht bewusst zwischen Methoden und Funktionen unterschieden. Das ist wie im Alltag, wo wir nicht bewusst zwischen Masse und Gewicht unterscheiden. Sie sind jedoch tatsächlich unterschiedlich, und diese Unterschiede beruhen auf der Verbindung zwischen ihnen!

Wie man definiert

Zuerst beziehen wir uns auf den englischen Originaltext, um die Unterschiede und Verbindungen in ihren Definitionen zu sehen:

A Funktionstyp ist (grob) ein Typ der Form (T1, ..., Tn) => U, der eine Kurzschreibweise für das Trait ist FunctionN in der Standardbibliothek. Anonyme Funktionen und Methodenwerte haben Funktionstypen, und Funktionstypen können als Teil von Wert-, Variablen- und Funktionsdeklarationen und -definitionen verwendet werden. Tatsächlich kann er Teil eines Methodentyps sein.

A Methodentyp ist ein Nicht-Wert-Typ. Das bedeutet, es gibt keinen Wert – kein Objekt, keine Instanz – mit einem Methodentyp. Wie oben erwähnt, ein Methodenwert hat tatsächlich einen Funktionstyp. Ein Methodentyp ist eine def Deklaration – alles über eine def außer ihrem Körper.

Beispiel:

scala> def m1(x:Int) = x+3
m1: (x: Int)Int    

scala> val f1 = (x: Int) => x+3
f1: Int => Int = <function1>

Siehst du? Die Definitionen von Methoden und Funktionen sind bereits in der Scala-Parser-Signatur dargestellt. `def m1(x: Int) = x+3` ist eine einfache Methodendefinition. In der Signatur zeigt `m1: (x: Int)Int`, dass Methode m1 einen Int-Parameter x hat und ihr Rückgabewert Int ist.

`val f1 = (x: Int) => x+3` ist eine Funktionsdefinition. In der Signatur des Parsers zeigt `f1: Int => Int = <function1>`, dass der Methodenkörper der Funktion f1 einen Int-Parameter akzeptiert und der Ausgabetyp Int ist.

Aus dem obigen Beispiel können wir eine Schlussfolgerung ziehen:

Eine Methode ist ein logischer Operationsblock, der mit `def` beginnt und eine Parameterliste hat (die fehlen kann), genau wie eine Member-Methode in einem Objekt oder einer Klasse.

Eine Funktion ist eine anonyme Methode (mit oder ohne Parameterliste), die einer Variablen (oder Konstante) zugewiesen wird, und ist ein Ausdruck, der das Konvertierungssymbol `=>` gefolgt von einem logischen Codeblock verwendet. Der logische Codeblock nach dem Konvertierungssymbol `=>` wird genauso geschrieben wie der Rumpf einer Methode.

Weitere Unterschiede

Eine Methode kann als Teil eines Ausdrucks auftreten (Aufrufen einer Funktion und Übergeben von Parametern), aber eine Methode (eine Methode mit Parametern) kann kein abschließender Ausdruck sein. Eine Methode ohne Parameter kann es, aber daraus wird ein Methodenaufruf, weil Scala das Weglassen der Klammern beim Aufruf einer Methode ohne Argumente erlaubt. Eine Funktion kann als abschließender Ausdruck auftreten.

scala> m1
<console>:12: error: missing arguments for method m1;
follow this method with `_' if you want to treat it as a partially applied function
       m1
       ^

scala> f1
res1: Int => Int = <function1>

Eine Methode kann keine Parameterliste haben, oder die Parameterliste kann leer sein. Eine Funktion muss jedoch eine Parameterliste haben (die ebenfalls leer sein kann). Ein Methodenname impliziert einen Methodenaufruf, während ein Funktionsname einfach die Funktion selbst repräsentiert:

scala> def m2 = 100;
m2: Int

scala> def m3() = 1000;
m3: ()Int

scala> var f2 = => 100;
<console>:1: error: illegal start of simple expression
var f2 = => 100;
         ^

scala> var f2 =()=> 100;
f2: () => Int = <function0>

scala> m2
res2: Int = 100

scala> m3
res3: Int = 1000

scala> m3()
res4: Int = 1000

scala> f2
res5: () => Int = <function0>

scala> f2()
res6: Int = 100

Wo eine Funktion erwartet wird, können wir eine Methode angeben.

Das liegt daran, dass die Methode automatisch in eine Funktion umgewandelt wird, wenn wir eine Methode angeben, wo eine Funktion erwartet wird. Dieses Verhalten heißt ETA-Expansion.

Hinweis:

Wo eine Funktion erwartet wird, können wir eine Methode verwenden.

Wo eine Funktion nicht erwartet wird, wird eine Methode nicht automatisch in eine Funktion umgewandelt.

In Scala werden Operatoren als Methoden interpretiert:

 
  • Präfixoperator: `op obj` wird als `obj.op` interpretiert
  • Infixoperator: `obj1 op obj2` wird als `obj1.op(obj2)` interpretiert
  • Postfixoperator: `obj op` wird als `obj.op` interpretiert
scala> val ml = List(1,2,3,4)
ml: List[Int] = List(1, 2, 3, 4)

scala> ml.map((x)=>2*x)
res0: List[Int] = List(2, 4, 6, 8)

scala> def m(x:Int) = 2*x
m: (x: Int)Int

scala> ml.map(m)
res1: List[Int] = List(2, 4, 6, 8)

scala> def m(x:Int) = 3*x
m: (x: Int)Int

scala> ml.map(m)
res2: List[Int] = List(3, 6, 9, 12)

Sie können einen Unterstrich nach dem Methodennamen hinzufügen, um ihn in eine Funktion umzuwandeln.

Hinweis:Zwischen dem Methodennamen und dem Unterstrich muss mindestens ein Leerzeichen stehen!

scala> def m3(x: Int): Int = x * x * x
m3: (x: Int)Int

scala> val f3 = m3_
<console>:10: error: not found: value m3_
       val f3 = m3_
                ^

scala> val f3 = m3 _
f3: Int => Int = <function1>

scala> f3(3)
res0: Int = 27

Ursprüngliche URL: https://www.cnblogs.com/shihuc/p/5082701.html