I have a class which defines a private maintenance method synch, which I want to always be invoked whenever any other method of the class is invoked. The classic way of doing this would of course be:
def method1 = {
synch
// ... do stuff
}
def method2 = {
synch
// ... do other stuff
}
However, is there any way to have this done implicitly, so that I do not have to invoke it explicitly like I do above?
EDIT:
If it is possible to do this, is it also possible to define if I want the synch method to be called after or before each other method?
You could create your custom wrapper using def macros
and Dynamic
like this:
import scala.reflect.macros.Context
import scala.language.experimental.macros
def applyDynamicImplementation(c: Context)(name: c.Expr[String])(args: c.Expr[Any]*) : c.Expr[Any] = {
import c.universe._
val nameStr = name match { case c.Expr(Literal(Constant(s: String))) => s }
if (nameStr != "sync")
c.Expr[Any](q"""{
val res = ${c.prefix}.t.${newTermName(nameStr)}(..$args)
${c.prefix}.t.sync
res
}""")
else
c.Expr[Any](q"""${c.prefix}.t.sync""")
}
import scala.language.dynamics
class SyncWrapper[T <: { def sync(): Unit }](val t: T) extends Dynamic {
def applyDynamic(name: String)(args: Any*): Any = macro applyDynamicImplementation
}
You'll have to use a compiler plugin for quasiquotes. If you want to call sync
before method - just switch val res = ...
and ${c.prefix}.t.sync
lines.
Usage:
class TestWithSync {
def test(a: String, b: String) = {println("test"); a + b}
def test2(s: String) = {println("test2"); s}
def sync() = println("sync")
}
val w = new SyncWrapper(new TestWithSync)
scala> w.test("a", "b")
test
sync
res0: String = ab
scala> w.test2("s")
test2
sync
res1: String = s
scala> w.invalidTest("a", "b")
<console>:2: error: value invalidTest is not a member of TestWithSync
w.invalidTest("a", "b")
^
You could do it with bytecode rewriting, or with macro annotations. Both would be quite complicated. Some things to consider:
Do you also want this to happen to inherited methods?
If synch
calls any other methods of this class, you will get an infinite loop.
Implicit definitions are those that the compiler is allowed to insert into a program in order to fix any of its type errors. For example, if x + y does not type check, then the compiler might change it to convert(x) + y, where convert is some available implicit conversion. If convert changes x into something that has a + method, then this change might fix a program so that it type checks and runs correctly. If convert really is just a simple conversion function, then leaving it out of the source code can be a clarification.
Basically implicit
is used for conversion implicitly so i tried it using an example i think it will help you:
scala> class c{
| implicit def synch(x: String)=x.toInt+20
| def f1(s: String):Int=s
| }
what am i doing is :
i am implicitely conversing String to int and adding 20 to that number so for that i defined one method that is synch
by using keyword implicit
that will take string
as an argument and after that convert value to int
and adding 20
to it.
in next method if arugment is string
and it return type is Int
so it will implicitely call that synch method
scala> val aty=new c
aty: c = c@1f4da09
scala> aty.f1("50")
res10: Int = 70