How do I assign an instance method to a value in Scala?
Related: How to assign a function to a value in Scala?
Considering:
class Foo{
def bar = println("bar")
def bat = println("bat")
}
How do I create it fnRef
so that it points to either Foo.bar
or Foo.bat
?
def deepFunction(foos : List[Foo], fnRef : ()=>Unit) = {
foos.map(_.fnRef) //May call either bar or bat
}
Bonus: is it possible to restrict fnRef to be just methods of that signature in the Foo class?
source to share
No. :-) Instead, you write your code in terms of first class functions. What makes this nice in Scala is that it will create a function literal from a _.method
type T => R
, where T
is the type of the parameter and R
is the return type of the method.
So, _.bar
they _.bat
will do Foo => Unit
:
scala> class Foo{
| def bar = println("bar")
| def bat = println("bat")
| }
defined class Foo
scala> def deepFunction(foos: List[Foo], fn: Foo => Unit) {
| foos.map(fn)
| }
deepFunction: (foos: List[Foo], fn: Foo => Unit)Unit
scala> deepFunction(List(new Foo, new Foo), _.bar)
bar
bar
scala> deepFunction(List(new Foo, new Foo), _.bat)
bat
bat
What's really nice about this approach is that you can use any function, not just member functions.
scala> def bam(f: Foo) { println("bam") }
bam: (f: Foo)Unit
scala> deepFunction(List(new Foo, new Foo), bam)
bam
bam
source to share
You can get a reference to a method as a function via a partial application:
scala> val foo = new Foo
foo: Foo = Foo@5dc22e67
scala> val fun = foo.bar _
fun: () => Unit = <function0>
scala> fun()
bar
This also works with multiple parameter lists:
scala> class Bar { def bar(s: String, t: String) = println(s+t) }
defined class Bar
scala> new Bar().bar _
res0: (String, String) => Unit = <function2>
source to share