tutorial software renault examples scala

software - scala vs java



¿Cuál es la función de aplicación en Scala? (3)

Aquí hay un pequeño ejemplo para aquellos que quieren leer rápidamente

object ApplyExample01 extends App { class Greeter1(var message: String) { println("A greeter-1 is being instantiated with message " + message) } class Greeter2 { def apply(message: String) = { println("A greeter-2 is being instantiated with message " + message) } } val g1: Greeter1 = new Greeter1("hello") val g2: Greeter2 = new Greeter2() g2("world") }

salida

Un greeter-1 está siendo instanciado con el mensaje hola.

Un greeter-2 está siendo instanciado con mundo de mensajes.

Nunca lo entendí a partir de los sustantivos idóneos e irrelevantes (¡una clase AddTwo tiene una apply que agrega dos!) Ejemplos.

Entiendo que es azúcar sintáctico, por lo que (deducí del contexto) debe haber sido diseñado para hacer que el código sea más intuitivo.

¿Qué significado da una clase con una función de apply ? ¿Para qué se usa y para qué propósitos hace que el código sea mejor (no maltratado, verificación de nombres, etc.)?

¿Cómo ayuda cuando se usa en un objeto compañero?


Los matemáticos tienen sus propias y divertidas formas, por lo que en lugar de decir "entonces llamamos función f pasarla x como parámetro", como diríamos los programadores, hablan de "aplicar la función f a su argumento x ".

En matemáticas y ciencias de la computación, Aplicar es una función que aplica funciones a los argumentos.
Wikipedia

apply sirve para cerrar la brecha entre los paradigmas orientados a objetos y funcionales en Scala. Cada función en Scala puede ser representada como un objeto. Cada función también tiene un tipo OO: por ejemplo, una función que toma un parámetro Int y devuelve un Int tendrá el tipo OO de Function1[Int,Int] .

// define a function in scala (x:Int) => x + 1 // assign an object representing the function to a variable val f = (x:Int) => x + 1

Como todo es un objeto en Scala f , ahora se puede tratar como una referencia al objeto Function1[Int,Int] . Por ejemplo, podemos llamar al método toString heredado de Any , que hubiera sido imposible para una función pura, porque las funciones no tienen métodos:

f.toString

O podríamos definir otro objeto Function1[Int,Int] llamando al método compose en f y encadenando dos funciones diferentes:

val f2 = f.compose((x:Int) => x - 1)

Ahora, si queremos ejecutar realmente la función, o como matemático dice "aplicar una función a sus argumentos", llamaríamos al método de apply en el objeto Function1[Int,Int] :

f2.apply(2)

Escribir f.apply(args) cada vez que quiera ejecutar una función representada como un objeto es la forma Orientada a Objetos, pero agregaría mucho desorden al código sin agregar mucha información adicional y sería bueno poder Utilice una notación más estándar, como f(args) . Ahí es donde entra el compilador Scala y siempre que tenemos una referencia f a un objeto de función y escribimos f (args) para aplicar argumentos a la función representada, el compilador expande silenciosamente f (args) al método de objeto llamado f.apply (args) .

Cada función en Scala puede tratarse como un objeto y también funciona de la otra manera: cada objeto puede tratarse como una función, siempre que tenga el método de apply . Tales objetos se pueden usar en la notación de la función:

// we will be able to use this object as a function, as well as an object object Foo { var y = 5 def apply (x: Int) = x + y } Foo (1) // using Foo object in function notation

Hay muchos casos de uso en los que nos gustaría tratar un objeto como una función. El escenario más común es un patrón de fábrica . En lugar de agregar el desorden al código usando un método de fábrica, podemos apply objeto a un conjunto de argumentos para crear una nueva instancia de una clase asociada:

List(1,2,3) // same as List.apply(1,2,3) but less clutter, functional notation // the way the factory method invocation would have looked // in other languages with OO notation - needless clutter List.instanceOf(1,2,3)

Entonces, el método de apply es solo una forma útil de cerrar la brecha entre las funciones y los objetos en Scala.


Viene de la idea de que a menudo desea aplicar algo a un objeto. El ejemplo más preciso es el de las fábricas. Cuando tiene una fábrica, desea aplicarle un parámetro para crear un objeto.

Los chicos de Scala pensaron que, como ocurre en muchas situaciones, podría ser bueno tener un atajo para poder apply . Por lo tanto, cuando asigna parámetros directamente a un objeto, se analiza como si pasara estos parámetros a la función de aplicación de ese objeto:

class MyAdder(x: Int) { def apply(y: Int) = x + y } val adder = new MyAdder(2) val result = adder(4) // equivalent to x.apply(4)

A menudo se usa en el objeto compañero, para proporcionar un buen método de fábrica para una clase o un rasgo, aquí hay un ejemplo:

trait A { val x: Int def myComplexStrategy: Int } object A { def apply(x: Int): A = new MyA(x) private class MyA(val x: Int) extends A { val myComplexStrategy = 42 } }

Desde la biblioteca estándar de scala, puede ver cómo se implementa scala.collection.Seq : Seq es un rasgo, por lo que la new Seq(1, 2) no se compilará, pero gracias al objeto compañero y la aplicación, puede llamar a la Seq(1, 2) y la implementación es elegida por el objeto compañero.