Los métodos apply y update
En scala podemos extender la sintaxis de llamada de funciones :
f(n1, n2, n3, …)
Si f es una función o un método, se ejecuta. De lo contrario, se
llama al método apply por lo tanto es equivalente a llamar a
f.apply(n1, n2, n3, …)
De la misma manera si se utiliza la notación de función con
asignación se llama al método update :
f(n1, n2, n3, …) = value
Es similar a llamar a :
f.update(n1, n2, n3, …, value)
Este mecanismo es utilizado en arrays y maps :
val scores = new scala.collection.mutable.HashMap[String, Int]
scores("Bob") = 100 // es como llamar a
scores.update("Bob", 100)
val bobsScore = scores("Bob") // es como llamar a
scores.apply("Bob")
El método apply también es usado para retornar instancias de
objetos, sin tener que llamar al constructor con el new :
class Fraction(n: Int, d: Int) {
}
object Fraction {
def apply(n: Int, d: Int) = new Fraction(n, d)
}
De esta manera podemos hacer lo siguiente:
val result = Fraction(3, 4) * Fraction(2, 5)
Extractors
Un extractor es un objeto que puede desaplicar un método. Se puede
pensar esto como el método contrario a el apply. Por ejemplo si el
apply agrega un elemento a una lista el extractor debería quitar
este elemento.
Por ejemplo el objeto Fraction tiene un método apply que retorna una
Fraction a partir de un numerador y un denominador. El extractor
debería retornar un numerador y un denominador a partir de una
Fraction.
object Fraction {
def unapply(input: Fraction) =
if (input.den == 0) None else Some((input.num, input.den))
}
Por lo general el método unapply retorna un Option dado que puede
haber un error cuando queremos desaplicar un método. En el ejemplo
si el denominador es 0 retorna None.
val Fraction(a, b) = f;
val tupleOption = Fraction.unapply(f)
if (tupleOption == None) throw new MatchError
// tupleOption is Some((t1 , t2))
En el ejemplo el método apply y unapply son inversos pero esto no es
obligatorio.