Scala hat sowohl Funktionen als auch Methoden. In den meisten Fällen können wir die Unterschiede zwischen ihnen ignorieren. Aber manchmal müssen wir ihre Unterschiede verstehen.

Methoden in Scala sind wie Methoden in Java; Methoden sind Teil einer Klasse. Eine Methode hat einen Namen, eine Typsignatur, manchmal Annotationen an der Methode und den funktionalen Implementierungscode (Bytecode) der Methode.

Funktionen in Scala sind vollständige Objekte. Scala verwendet 22 Traits, um das Konzept der Funktionen zu abstrahieren. Diese 22 Traits reichen von Function1 bis Function22:

Wie in der obigen Abbildung gezeigt, repräsentiert Function10: eine Funktion mit 10 formalen Parametern und einem Rückgabewert R (kovariant).

Funktionen in Scala sind tatsächlich Objekte von Klassen, die von diesen Traits erben. Zum Beispiel definieren wir eine Funktion durch ein Funktionsliteral:

Tatsächlich ist die obige Funktionsdefinition äquivalent zur folgenden Definition:

Da Function2 ein Trait ist, kann es nicht direkt mit new instanziiert werden. Das obigenew Function2[Int,Int,Int](){}definiert und instanziiert eigentlich ein Objekt einer Klasse, die das Trait Function2 implementiert.

apply ist syntaktischer Zucker in Scala: Wenn obj() auf einem Objekt obj aufgerufen wird, wandelt der Scala-Compiler es in obj.apply() um; wenn clazz() auf einer Klasse clazz aufgerufen wird, wandelt der Scala-Compiler es in clazz_company_obj.apply() um, wobei clazz_company_obj das Companion-Objekt von clazz ist.

Die konkreten Unterschiede sind wie folgt zusammengefasst:

1. Eine Methode kann nicht als eigenständiger Ausdruck existieren (außer bei Methoden ohne Parameter), eine Funktion hingegen schon. Zum Beispiel:

Im obigen Beispiel haben wir zuerst eine Methode m definiert und dann eine Funktion f definiert. Dann verwenden wir den Funktionsnamen (den Funktionswert) als abschließenden Ausdruck. Da f selbst

ein Objekt ist (ein Objekt, das das Trait FunctionN implementiert), ist diese Verwendung völlig korrekt. Aber wenn wir den Methodennamen als abschließenden Ausdruck verwenden, verursacht das einen Fehler.

2. Eine Funktion muss eine Parameterliste haben, während eine Methode keine Parameterliste haben kann.

Im obigen Beispiel akzeptiert die Methode m1 null Parameter, daher kann die Parameterliste weggelassen werden. Aber eine Funktion kann die Parameterliste nicht weglassen.

3. Ein Methodenname ist ein Methodenaufruf, während ein Funktionsname nur das Funktionsobjekt selbst repräsentiert.

Das ist leichter zu verstehen. Denn die Variable, die das Funktionsliteral enthält (auch Funktionsname oder Funktionswert genannt), ist selbst ein Objekt einer Klasse, die das Trait FunctionN implementiert. Um die apply-Methode des Objekts aufzurufen, muss man die Syntax obj() verwenden. Daher ruft man die Funktion auf, indem man Klammern hinter den Funktionsnamen setzt. Wie folgt:

4. Wenn eine Funktion benötigt wird und eine Methode übergeben wird, wird automatisch eine ETA-Expansion (Umwandlung einer Methode in eine Funktion) durchgeführt.

Wenn wir eine Methode direkt einer Variablen zuweisen, wird ein Fehler gemeldet. Wenn wir den Typ der Variablen als Funktion angeben, kann sie die Kompilierung bestehen. Wie folgt:

Natürlich können wir auch erzwingen, dass eine Methode in eine Funktion umgewandelt wird, wobei Scalas partiell angewendete Funktionen verwendet werden:

5. Ein By-Name-Parameter ist im Wesentlichen eine Methode.

Ein By-Name-Parameter ist im Wesentlichen eine Methode mit einer leeren Parameterliste. Wie folgt:

Der obige Code definiert tatsächlich eine Methode m1, und der Parameter von m1 ist ein By-Name-Parameter (Methode). Da bei einer Methode ohne Parameter der Methodenname der Methodenaufruf ist , führt List(x, x) tatsächlich zwei Methodenaufrufe aus.

WeilList(x,x)zwei Methodenaufrufe ausgeführt werden, erhält man zwei verschiedene Werte.

Wenn wir die Definition von m1 leicht ändern und x zuerst zwischenspeichern, wird das Ergebnis ganz anders sein als zuvor.

Originalartikel: https://blog.csdn.net/u012302488/article/details/50543661