En Scala existen tanto funciones como métodos. En la mayoría de los casos podemos ignorar la diferencia entre ellos. Pero a veces debemos conocer sus diferencias.
Los métodos en Scala son como los métodos de Java: un método forma parte de una clase. Un método tiene nombre, firma de tipo, a veces anotaciones sobre el método, y el código de implementación de la funcionalidad (bytecode).
Una función en Scala es un objeto completo. En Scala, el concepto de función se abstrae mediante 22 traits. Estos 22 traits van desde Function1 hasta Function22:
Como se muestra en la figura anterior, Function10 representa: una función con 10 parámetros formales y valor de retorno R (covariante).
De hecho, una función en Scala es un objeto de una clase que hereda estos traits. Por ejemplo: definimos una función mediante un literal de función.
En realidad, la forma de definir la función anterior es equivalente a la siguiente forma:
Dado que Function2 es un trait, no se puede usar new directamente. Lo anteriornew Function2[Int,Int,Int](){}en realidad es definir e instanciar un objeto de una clase que implementa el trait Function2.
apply es azúcar sintáctico en Scala: al invocar obj() sobre un objeto obj, el compilador de Scala lo convierte en obj.apply(); al invocar clazz() sobre una clase clazz, el compilador de Scala lo convierte en clazz_company_obj.apply(), donde clazz_company_obj es el objeto acompañante de clazz.
Las diferencias específicas se resumen en los siguientes puntos:
1. Un método no puede existir como una expresión independiente (excepto los métodos sin parámetros), pero una función sí puede. Por ejemplo:
En el ejemplo anterior, primero definimos un método m, y luego definimos una función f. Después usamos el nombre de la función (el valor de la función) como expresión final. Como f en sí es
un objeto (un objeto que implementa el trait FunctionN), por lo que esta forma de uso es completamente correcta. Pero si usamos el nombre del método como expresión final, se producirá un error.
2. Las funciones deben tener una lista de parámetros, mientras que los métodos pueden no tenerla.
En el ejemplo anterior, el método m1 acepta cero parámetros, por lo que se puede omitir la lista de parámetros. Pero las funciones no pueden omitir la lista de parámetros.
3. El nombre de un método es una invocación al método, mientras que el nombre de una función solo representa al objeto de la función en sí.
Esto es fácil de entender. Porque la variable que contiene el literal de función (también llamada nombre de función o valor de función) es en sí misma un objeto de una clase que implementa el trait FunctionN. Para invocar el método apply del objeto, se necesita usar la sintaxis obj(). Por lo tanto, agregar paréntesis después del nombre de la función es invocar la función. Como sigue:
4. Cuando se necesita una función, si se pasa un método, se realiza automáticamente la expansión ETA (convertir el método en una función).
Si asignamos directamente un método a una variable, se producirá un error. Si especificamos que el tipo de la variable es una función, entonces la compilación será exitosa. Como sigue:
Por supuesto, también podemos forzar la conversión de un método a una función, para lo cual se utilizan las funciones de aplicación parcial en Scala:
5. Un parámetro por nombre es esencialmente un método.
Un parámetro por nombre es en esencia un método con una lista de parámetros vacía, como sigue:
El código anterior realmente define un método m1, cuyo parámetro es un parámetro por nombre (método). Dado que para un método sin parámetros, el nombre del método es la invocación del método, List(x,x) en realidad realiza dos invocaciones al método.
Dado queList(x,x)se realizan dos invocaciones al método, por lo que se obtienen dos valores diferentes.
Si modificamos ligeramente la definición de m1 y almacenamos en caché x primero, el resultado será muy diferente al anterior.
Texto original: https://blog.csdn.net/u012302488/article/details/50543661