Search code examples
scalapass-by-name

Use a stored value in the superclass' constructor when extending a class taking a by-name parameter


I have a case where I wish to extend a class that takes by-name parameter in it's constructor:

class Extension(something: Something) 
  extends Base(something.doSomething(something.getSomething(false))

class Base(expression: => Result) {
  ...
}

However, the call to something.getSomething(false) causes side-effects, and so can't be called multiple times.

How can I store the result of something.getSomething(false), before passing it to the superclass' constructor?


Solution

  • We can do this by having two constructors - one that takes both the parameter and generated parameter, and one that takes only the parameter the user should provide.

    We make the first constructor private, so people don't accidentally use it, then we use the second constructor to construct the value and pass it into the first.

    class Extension private (something: Something, generatedFromSomething: Generated)
        extends Base(something.doSomething(generatedFromSomething) {
      def this(something: Something) = this(something, something.getSomething(false))
    }
    

    As ErikAllik suggests in the comments, it may be best to simply avoid inheritance if possible, as it becomes trivial to do this outside of that case:

    def extended(something: Something) = {
      val generatedFromSomething = something.getSomething(false)
      new Base(something.doSomething(generatedFromSomething)
    }