2010-01-18 12 views
5

Diciamo che ho un metodo che prevede un altro metodo come parametro. È possibile inviare i metodi di istanza di un oggetto per quel parametro? Come gestirò i metodi che non hanno parametri?Posso passare un metodo di istanza di un oggetto a un metodo che prevede un callback in Scala?

scriverò alcuni pseudocodice:

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 

se per esempio ho un ArrayList, in questo modo:

val a = new ArrayList() 

come potrei inviare è add Metodo parametro per myMethod1, ed è Metodo size come parametro per myMethod2?

+2

E 'importante conoscere e tenere a mente che nei metodi e le funzioni Scala sono molto cose differenti. I metodi non sono entità di prima classe, ma le funzioni lo sono. Quindi (riflessione a parte), nessun metodo prende un altro metodo come parametro. L'applicazione parziale può essere utilizzata con entrambi i metodi o funzioni e fornisce sempre una funzione. –

risposta

4

Penso che myMethod4 possa essere ciò che intendi quando dici: "Non è possibile fare riferimento a a.size e invocarlo quando necessario?".

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

puoi spiegare come funzionano le parate vuote in method2/3/4? – Geo

+1

Un blocco '{a; b; c} 'deve contenere una sequenza di espressioni e dichiarazioni (var, val, classe, funzione, tratto, oggetto). Deve finire con un'espressione. Per chiarezza, ho assegnato il risultato di 'f' a un valore val', quindi ho dovuto seguirlo con un'espressione conforme al tipo atteso del blocco, che in questo caso è il tipo dichiarato della funzione:' unit'. '()' è l'unica istanza del tipo 'Unità'. Funzionerebbe anche un 'return' vuoto. Come sarebbe un'espressione di qualsiasi altro tipo, dato che qualsiasi valore può essere convertito in "Unità". – retronym

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

myMethod(a.add _, a.size) 

Void è rappresentato attraverso il tipo Unit.

Modifica: Attraverso l'utilizzo sopra di => Int, size viene passato per nome, il che significa che viene sempre rivalutato quando necessario.

+0

Non è possibile fare riferimento a "a.size" e richiamarlo quando necessario? – Geo

+0

Vuoi dire dimensione di passaggio: Int per nome? def myMethod (callback: Int => Unità, dimensione: => Int) – davetron5000

5

Il tipo di una funzione in Scala è denotata

(Types,To,Pass) => ReturnType 

(è possibile lasciare fuori le parentesi se c'è solo un singolo tipo di pass), e il modo di convertire un metodo in un funzione per passare a un altro metodo è

myObject.myMethod _

Così, mettendo insieme questi - e prestando attenzione ai tipi di classi 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] 

(Si noti che ArrayList ha un componente aggiuntivo che prende un oggetto e restituisce un valore booleano -. Non uno che restituisce void)

Problemi correlati