2010-01-18 29 views
5

Digamos que tengo un método que espera otro método como parámetro. ¿Es posible enviar los métodos de instancia de un objeto para ese parámetro? ¿Cómo manejaría los métodos que no tienen parámetros?¿Puedo pasar el método de instancia de un objeto a un método que espera una devolución de llamada en Scala?

voy a escribir algunos pseudocódigo:

void myMethod1(callback<void,int> otherFunc); // imagine a function returning void, and taking a int parameter 

void myMethod2(callback<int,void> otherFunc); // function returning void, not taking params 

si por ejemplo tengo un ArrayList, así:

val a = new ArrayList() 

cómo podría enviar es add método como parámetro para myMethod1, y es size método como parámetro para myMethod2?

+2

Es importante conocer y tener en cuenta que en los métodos y funciones Scala son muy cosas diferentes. Los métodos no son entidades de primera clase, pero sí funciones. Por lo tanto (reflexión a un lado), ningún método toma otro método como parámetro. La aplicación parcial se puede usar con métodos o funciones y siempre produce una función. –

Respuesta

4

Creo que myMethod4 puede ser lo que quieres decir cuando dices: "¿No es posible hacer referencia a a.size e invocarlo cuando sea necesario?".

def myMethod1(f: Int => Unit): Unit = f(1) 

def myMethod2(f:() => Int): Unit = { 
    val value = f // f is function, taking no arguments, and returning an int. 
       // we invoke it here. 
() 
} 

def myMethod3(f: => Int): Unit = { 
    val value = f // f is call by name parameter. 
() 
} 

def myMethod4[A](f: A => Int, a: A): Unit = { 
    val value = f(a) 
() 
} 

import java.util.ArrayList 

val a = new ArrayList[Int](1) 
myMethod1((i: Int) => a.add(i)) 
myMethod1(a.add(_))  // shorthand for the above 
myMethod2(() => a.size) // a.size is not evaluated, it is enclosed in an anonymous function definition. 
myMethod3(a.size)  // a.size is not evaluated here, it is passed as a by-name parameter. 
myMethod4((al: ArrayList[Int]) => al.size, a) 
myMethod4((_: ArrayList[Int]).size, a) 
myMethod4[ArrayList[Int]](_.size, a) 
+0

¿puede explicar cómo funcionan las parantheses vacías en method2/3/4? – Geo

+1

Un bloque '{a; segundo; c} 'debe contener una secuencia de expresiones y declaraciones (var, val, clase, función, rasgo, objeto). Debe terminar con una expresión. Para mayor claridad, asigné el resultado de 'f' a un val' value', así que necesitaba seguir esto con una expresión que conformara el tipo esperado del bloque, que en este caso es el tipo declarado de la función: ' Unidad'. '()' es la única instancia del tipo 'Unit'. Un 'retorno' vacío también funcionaría. Como lo haría una expresión de cualquier otro tipo, ya que cualquier valor se puede convertir a tipo 'Unidad'. – retronym

4
def myMethod(callback : Int => Unit, size : => Int) = ... 

myMethod(a.add _, a.size) 

Void se representa a través del tipo Unit.

Editar: A través del uso anterior de => Int, size se pasa por su nombre, lo que significa que siempre se vuelve a evaluar cuando sea necesario.

+0

¿No es posible hacer referencia a 'a.size' e invocarlo cuando sea necesario? – Geo

+0

¿Quiere decir pasar el tamaño: Int por nombre? def myMethod (devolución de llamada: Int => Unidad, tamaño: => Int) – davetron5000

5

El tipo de una función en Scala se denota

(Types,To,Pass) => ReturnType 

(se puede dejar fuera de la parens si sólo hay un único tipo de pasar), y la manera de convertir un método en una función para pasar a otro método es

myObject.myMethod _

lo tanto, poner estos juntos - y prestar atención a los tipos de las clases de Java:

scala> def addMySize(adder: Int => Boolean, sizer:() => Int) = adder(sizer()) 
addMySize: ((Int) => Boolean,() => Int)Boolean 

scala> val a = new java.util.ArrayList[Int]() 
a: java.util.ArrayList[Int] = [] 

scala> addMySize(a.add _, a.size _) 
res0: Boolean = true 

scala> addMySize(a.add _, a.size _) 
res1: Boolean = true 

scala> println(a) 
[0, 1] 

(Tenga en cuenta que ArrayList tiene un complemento que toma un objeto y devuelve un valor lógico -. No uno que devuelve void)

Cuestiones relacionadas