Reputation: 14060
Say I have a trait like this
trait X {
def foo(param: String): Int
}
and I want to override it with a function value, I have to do this:
class XImpl extends X {
private val fooF: String => Int = ???
override def foo(param: String): Int = fooF(param)
}
because the following does not work
class XImpl extends X {
override val foo: String => Int = ???
}
/*
error: class XImpl needs to be abstract. Missing implementation for:
def foo(param: String): Int // inherited from trait X
^
error: value foo overrides nothing.
Note: the super classes of class XImpl contain the following, non final members named foo:
def foo(param: String): Int
*/
Is it possible to directly implement/override the trait method with the function value in some way and avoid the forwarder?
Upvotes: 2
Views: 767
Reputation: 27356
The simple answer is that you cannot override a method with a function value because they are not the same type.
A method must be called on a particular instance of a class (even if the method itself does not use any fields in that class).
A function value stands alone and can be called without any additional information.
A method can be converted a function value using eta expansion x.foo _
. This creates a function value which has the class value embedded within it.
val x: X = ???
val etaFoo: String => Int = x.foo _
In this case Scala will actually do the eta expansion for you so the _
is optional, but it is required in more complex uses and is good practice to keep it there so show that eta expansion is happening.
To convert a function value to a method you need to define a method as shown in the question.
Eta expansion works with methods with multiple parameters:
trait X2 {
def foo2(p1: String, p2: Int): String
}
val x2: X2 = ???
val etaFoo2: (String, Int) => String = x2.foo2 _
Upvotes: 6