"return this" in a covariant trait that return actual type
Asked Answered
C

1

7

This was probably asked before, but I have this problem:

trait Container[+A] {
  def a: A

  def methodWithSideEffect() = {
    // perform some side effecting work
    this
  }
}

class IntContainer(val a: Int) extends Container[Int]

How do I have the methodWithSideEffect in IntContainer return an IntContainer instead of a Container[Int]? I would also want not to add any parameter to the Container trait, at least from the API user point of view. Note that I did make a workaround with an implicit:

implicit class MyContainer[A <: Container[_]](c: A) {
  def methodWithSideEffect(): A = {
    // perform work
    c
  }
}

However, I am quite sure there is some way to do this more elegantly.

Contrapositive answered 9/3, 2014 at 21:36 Comment(0)
M
14

You can do this with a self type:

trait Container[+A] { self =>
  def a: A

  def methodWithSideEffect(): self.type = {
    // perform some side effecting work
    this
  }
}

class IntContainer(val a: Int) extends Container[Int]

...

val x: IntContainer = new IntContainer(42).methodWithSideEffect()

Or simply with this.type:

trait Container[+A] {
  def a: A

  def methodWithSideEffect(): this.type = {
    // perform some side effecting work
    this
  }
}

class IntContainer(val a: Int) extends Container[Int]
Mitchelmitchell answered 9/3, 2014 at 21:50 Comment(2)
Or simply this.typePleasure
Thank you, I was sure it was an easy question :)Contrapositive

© 2022 - 2024 — McMap. All rights reserved.