dtech
dtech

Reputation: 14060

Overriding a trait method with a function value

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

Answers (1)

Tim
Tim

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

Related Questions