1

Say we have a Scala trait

trait Foo {
  def bar(baz: Qux): Quux
  def corge: Grault
}

and we want to implement it in such a way that the implementation of bar() can be handled by an anonymous function. We can do this:

class FooImpl1(_bar: (Qux) => Quux, val corge: Grault) extends Foo {
  override def bar(baz: Qux) = { _bar(baz) }
}

allowing, e.g.:

val foo: Foo = new FooImpl({ qux: Qux => qux.asQuux()}, someGrault)

But this seems unnecessarily verbose (and also introduces the dreaded, and clunky, leading underscore).

Naively, noting that def corge in Foo is implemented by val corge in FooImpl1, it seems it should be possible to do something like this:

class FooImpl2(val bar: (Qux) => Quux, val corge: Grault) extends Foo {}

But we can't, presumably because Foo.bar doesn't return a function, it is a function (or rather a method).

Is there anything cleaner than FooImpl1 that we can do here?

2 Answers 2

1

If you have control of the trait, you could try modifying it instead:

trait Foo {
  val bar: Function1[Qux, Quux]
  def corge: Grault
}

which makes your FooImpl2 definition possible. Here's an example from an Eclipse ScalaWorksheet:

package so

object ClassExperiment {
  type Qux = Int
  type Quux = Boolean
  type Grault = String

  trait Foo {
    val bar: Function1[Qux, Quux]
    def corge: Grault
  }

  class FooImpl2(val bar: (Qux) => Quux, val corge: Grault) extends Foo {
    def blue = bar( 9 )
  }

  val foo = new FooImpl2( { a: Qux => a == 4 }, new Grault("monkey") )
                                                  //> foo  : so.ClassExperiment.FooImpl2 = so.ClassExperiment$FooImpl2@68f
                                                  //| e748f

  foo.blue                                        //> res0: so.ClassExperiment.Quux = false
  foo.bar( 4 )                                    //> res1: so.ClassExperiment.Quux = true
  foo.bar( 7 )                                    //> res2: so.ClassExperiment.Quux = false
  foo.corge                                       //> res3: so.ClassExperiment.Grault = monkey
}

I left off the Foo type specifier when creating foo so I could show the call output to blue.

Sign up to request clarification or add additional context in comments.

1 Comment

In the general case it's more likely that implementations are just going to implement the method.
0

Why not just do this?

val foo = new Foo { 
   def bar(qux : Qux) = qux.asQuux 
   val corge = someGrault
}

It doesn't seem like defining a FooImpl class really buys you anything.

2 Comments

He wants to be able to specify the behaviour of bar() separately from the construction of the class
It's a toy example. IRL it's obviously not worth doing unless you have multiple implementations.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.