5

I have a class with the (admittedly stupid) name Application. There is also a class ApplicationRepository that features a private save(Application) method.

I would like to add a method to ApplicationRepository that creates an Application instance (from exactly the constructor parameters) and saves it. I do not want to expose save or use a parameter of type Application.

def createApplication(firstDay:String, lastDay:String, details:String, substitute:User, projectManager:User) = {
  val a = Application(firstDay, lastDay, details, substitute, projectManager)
  save(a)
}

Basically my question boils down to:

In Scala - can I create a "proxy" function with the same parameter list as a "proxied" function, pass all the arguments without caring about them, and then do different stuff?

3 Answers3

2

2 years later I ran into this situation and I solved my case using java proxies. The actual magic is built in using java's invocation handler () and Proxy ()

Hat Tip to (How to use java proxy in scala) where this answer is based on.

scala> :paste
// Entering paste mode (ctrl-D to finish)

import java.lang.reflect.{Method, InvocationHandler, Proxy}

object ProxyTesting {

  // You need an interface or java's proxy to work.
  trait ProxyTestIface {
    // your function signature here
    def createApplication( firstDay:String, lastDay:String, details:String, substitute:String, projectManager:String):Unit = ???
  }

  // your object implementation
  class ProxyTest extends ProxyTestIface{
    // your function implementation
    override def createApplication( firstDay:String, lastDay:String, details:String, substitute:String, projectManager:String):Unit = {

      println("Actual Function is called")

      Unit
    }
  }

  def test() {
    val obj = new ProxyTest

    val impl = Proxy.newProxyInstance(
      obj.getClass.getClassLoader,
      Array(classOf[ProxyTestIface]),
      new InvocationHandler {
        def invoke(proxy: scala.AnyRef, method: Method, args: Array[AnyRef]): AnyRef = {
          // this shows you can execute prior and post your decorated function.
          println(s"Proxy Funcion is called: ${args.mkString(",")}")
          val res = method.invoke(obj, args:_*)
          println(s"Proxy Funcion is called: 2nd time ${args.mkString(",")}")
          res
        }
      }
    ).asInstanceOf[ProxyTestIface]

    impl.createApplication("firstDayMsg", "lastDayMsg", "detailsMsg", "substituteMsg", "projgMgrMsg")
  }

}

// Exiting paste mode, now interpreting.

import java.lang.reflect.{Method, InvocationHandler, Proxy}
defined object ProxyTesting

scala> ProxyTesting.test()
Proxy Funcion is called: firstDayMsg,lastDayMsg,detailsMsg,substituteMsg,projgMgrMsg
Actual Funcion is called
Proxy Funcion is called: 2nd time firstDayMsg,lastDayMsg,detailsMsg,substituteMsg,projgMgrMsg

scala>
Community
  • 1
  • 1
critium
  • 612
  • 5
  • 16
0

You could do it with macros. It seems like a rare enough case that I wouldn't bother.

Alexey Romanov
  • 167,066
  • 35
  • 309
  • 487
-1

I think that you cannot omit arguments. But you should try to define companion object for your's class:

object Application {
  def apply(firstDay:String, lastDay:String, details:String, substitute:User, projectManager:User) = {
    //place for your logic
  }
}

This is quite common way to hide construction logic inside factory and Scala gives you factory out of the box. You could also try to use mixins and dynamically mixin saving logic inside constructor but I think that this would be bad design.

bkowalikpl
  • 817
  • 5
  • 11
  • Thanks for the suggestion. I already have a companion object in place (there's no 'new' in front of Application(...) in my code above). – Klaus Baumgartner Dec 20 '13 at 08:20