Given a class `Base`, Is there a way to run some c...
# getting-started
k
Given a class
Base
, Is there a way to run some code before and after every method call on Base's subclasses?
a
Copy code
open class Base{
  fun mustRun() {
    // . . .
  }
  inline fun <T> withMustRun(block: ()->T) {
    mustRun()
    val res = block()
    mustRun()
    return res;
  }
}
and then you can now do things like
Copy code
class Child: Base() {
  fun methodOne() = withMustRun {
    // doStuff here
  }
}
Wrapping every method using
withMustRun
will run
mustRun
before and after your code block
👍 2
e
you can't force force every child method to be wrapped
there is another pattern:
Copy code
open class Base {
    /* final */ fun foo() {
        println("before foo()")
        doFoo()
        println("after foo()")
    }
    protected abstract fun doFoo()
}
class Child : Base() {
    override fun doFoo() { ... }
}
this prevents unrelated code from invoking
doFoo
directly, only
foo
which wraps it
👆 1
depending on what you are trying to achieve, there may be a better way
s
If you execute your program within the Spring framework you could use Aspect oriented programming to achieve this, I think (I've only used annotations to target classes, but it probably also works for subclasses somehow?!? 🤔) I've used this once in a Kotlin project and it worked as expected. https://www.baeldung.com/spring-aop-advice-tutorial
👍 1
You probably don't need Spring, just the AspectJ lib that Spring uses itself: https://www.eclipse.org/aspectj/ But it might be less convinient?? I've never used it directly.
e
aspectj can do something like this… although all the subclasses must be known, or at least be in a known package, otherwise you can't match all the pointcuts
k
thanks guys for the suggestions, I've tried them out but they call kind of fall short of everything I need to do. Possibly AOP would work, but that's a too big hammer for this usecase! I like the approach of @andylamax, but then I'm stuck with a single arity functions, since there's no way to be polymorphic over the functions arity (right?) Besides that I need the pre/post blocks of code to execute without knowing what additional functions will be implemented in the subclasses...
m
Given your requirements, AOP is the right tool for the job. What scares you into thinking it’s a too big hammer? You just need Aspectj for your solution. Alternatively you can use proxetta for a simpler code-only API.
s
no, you're not stuck with a single arity since each lambda
withMustRun
will just have access to whatever parameters the invoking functions has without those parameters being explicitly provided to it. So
Copy code
class SubBase: Base() {
  fun methodOne(a: Int) = withMustRun {
    // doStuff here with a
  }

  fun methodTwo(s1: String, s2: String) = withMustRun {
    // doStuff here with s1 & s2
  }
}
will both work. But since you you have to use
withMustRun
explicitly anyway, I'd declare it and
mustRun
top-level and not as part of
Base
.
2
👍 1
k
@Stephan Schroeder oooooooooohhhh, right! Silly me, can't believe I didn't see that one 😆. That might just be the trick, I'm trying to keep the dependencies and complexity to the absolute minimum here... Would love to try out AOP, but that'll be for another project...