John Doe
John Doe

Reputation: 277

How to extend a Scala class with functionality without modifying this particular class?

Let's say I want to encapsulate functionality of a class, meaning I want to introduce a proxy between clients and this particular class. For example, Play's Result class has the following method:

  /**
   * Adds headers to this result.
   *
   * For example:
   * {{{
   * Ok("Hello world").withHeaders(ETAG -> "0")
   * }}}
   *
   * @param headers the headers to add to this result.
   * @return the new result
   */
  def withHeaders(headers: (String, String)*): Result = {
    copy(header = header.copy(headers = header.headers ++ headers))
  }

Let's assume that I don't want to use this method directly, but instead I want to use a proxy. So instead of calling Redirect(controllers.app.routes.Application.index).withHeaders(<XYZ>) I want to call my own method which subsequently calls .withHeaders(<XYZ>):

Redirect(controllers.app.routes.Application.index).customWithHeaders(<XYZ>)

How can this be implemented? Can this be done by implementing a trait which will be extended by controllers?

Upvotes: 0

Views: 51

Answers (1)

Nagarjuna Pamu
Nagarjuna Pamu

Reputation: 14825

import play.api.mvc.Result

implicit class ResultUtils (result: Result) {
    def withCustomHeaders(pairs: (String, String)*): Result = result.withHeaders(pairs: _*)
}

with ResultUtils in scope, you can now do Redirect(something).withCustomHeaders

Package Object

package object common {
    implicit class ResultUtils (result: Result) {
      def withCustomHeaders(pairs: (String, String)*): Result = result.withHeaders(pairs: _*)
    }
}

import common._ //import common and get this class in scope

Trait

trait Implicits {
  implicit class ResultUtils (result: Result) {
      def withCustomHeaders(pairs: (String, String)*): Result = result.withHeaders(pairs: _*)
    }
}

class ApplicationController @Inject() () extends Controller extends Something with Implicits {
  def fooAction = Action { Ok("bar").withCustomHeaders("foo" -> "bar") }
}

Upvotes: 1

Related Questions