Могу ли я передать метод экземпляра объекта методу, ожидающему обратный вызов в Scala? - PullRequest
5 голосов
/ 18 января 2010

Допустим, у меня есть метод, ожидающий другого метода в качестве параметра. Можно ли отправить методы экземпляра объекта для этого параметра? Как бы я обработал методы, которые не имеют параметров?

Я напишу какой-нибудь псевдокод:

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

если, например, у меня есть ArrayList, например:

val a = new ArrayList()

как я могу отправить его add метод в качестве параметра для myMethod1, и это size метод как параметр для myMethod2?

Ответы [ 3 ]

5 голосов
/ 18 января 2010

Тип функции в Scala обозначается

(Types,To,Pass) => ReturnType

(вы можете опустить парены, если есть только один тип для передачи), и способ преобразования метода в функцию для передачи другому методу -

myObject.myMethod _

Итак, собрав их вместе и обращая внимание на типы классов 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]

(Обратите внимание, что ArrayList имеет дополнение, которое принимает объект и возвращает логическое значение, а не возвращающее void.)

4 голосов
/ 18 января 2010

Я думаю, myMethod4 может быть тем, что вы имеете в виду, когда говорите: «Разве нельзя ссылаться на a.size и вызывать его при необходимости?».

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)
4 голосов
/ 18 января 2010
def myMethod(callback : Int => Unit, size : => Int) = ...

myMethod(a.add _, a.size)

Void представляется через тип Unit.

Редактировать: При использовании вышеупомянутого => Int, size передается по имени, что означает, что оно всегда переоценивается, когданеобходимо.

...