Как передать метод класса в качестве параметра в Scala
допустим у меня есть класс C с некоторыми методами
def class C {
def f1():Int = ...
def f2():Int = ...
}
теперь я хотел бы метод, который принимает два экземпляра C, а также метод C, но я не знаю, что такое типы f1, f2, и как их вызвать. Я думаю, что это будет выглядеть как
def cmp(first:C, second:C, t:() => Int): Boolean = {
first.t < second.t
}
это жалуется, что t не является методом C. Конечно, должен быть способ выразить это.
3 ответов
def cmp(first:C, second:C, t: C => Int): Boolean = {
t(first) < t(second)
}
затем...
val c1 = new C
val c2 = new C
cmp(c1, c2, _.f1())
cmp(c1, c2, _.f2())
это использование анонимных функций. Последние две строки эквивалентны:
cmp(c1, c2, {c: C => c.f1()})
cmp(c1, c2, {c: C => c.f2()})
вы не можете передать ссылку на элемент метод per se, если вы не используете какое-то отражение.
вы можете просто передать ссылки на метод вместо этого:
object DoOperation extends App {
class C(val x: Int) {
def f1():Int = x-1
def f2():Int = x+1
}
def cmp(first: () => Int, second: () => Int): Boolean = {
first() < second()
}
override def main(args: Array[String]) {
println(cmp(new C(1).f1,new C(0).f2)) //prints "true"
println(cmp(new C(1).f2,new C(1).f1)) //prints "false"
}
}
методы будут закрыты над соответствующими экземплярами объектов, поэтому чистый эффект эквивалентен тому, что вы, по-видимому, хотите выполнить.
этот подход также может работать:
@ class myClass {
def double(x: Int): Int = x * 2
def triple(x: Int): Int = x * 3
}
defined class myClass
@ val instance = new myClass
instance: myClass = ammonite.$sess.cmd0$myClass@4195105b
@ def callArbitraryMethod(instance: myClass, f: (myClass, Int) => Int, x: Int): Int = f(instance, x)
defined function callArbitraryMethod
@ val f = (instance: myClass, x: Int) => instance.double(x)
f: (myClass, Int) => Int = ammonite.$sess.cmd3$$$Lambda65/11731022@3b8b4846
@ callArbitraryMethod(instance, f, 10)
res4: Int = 20