[Feature Request] Call by need interface delegates


#1

I have a cache of objects which are either in RAM or serialised to the disc. Now I want to make a class a class which has the same interface as the cached objects and delegates method calls by either querying whether the requested object is in memory and the making a direct call to it or loading the object from the disc and invoking the method on the loaded object. On the first view kotlins interface delegation seems to be perfect for this kind of problem.

interface Component {
    fun func()
}
class ComponentImpl: Component {
    override fun func() {}
}
class VirtualComponent: Component by getComponent() {
    companion object {
        fun getComponent(): Component 
             = queryComponent() ?: loadComponent()
    }
}

But the problem is that getComponent() would be called when VirtualComponent is created. What I need is that getComponent would be called when a method like func is invoked.
So at the moment I had to write:

class VirtualComponent: Component {
     override fun func() {
        getComponent().func()
    }
}

I have three ideas for syntax for that feature in descending elegance:

  1. delegate keyword after by
    Delegates the interface to a delegate
    Example:
class CallByNeed<T>(private val call: () -> T) {
    operator fun getValue(thisRef: Any, property: KProperty<*>): T = call()
}
fun <T> callByNeed(block: () -> T) = CallByNeed(block)
class VirtualDelegate : Componenent by delegate callByNeed { getComponent } 

Pros:

  • Very general - You could use other delegates too
  • Backward compatible
    Cons:
  • bit clumsy, maybe it would have been good to make the above standard without the delegate keyword
  1. Braces:
    Example:
    class VirtualDelegate : Componenent by { getComponent }
    Pros:
  • Simple
  • Does what you expect
    Cons:
  • Breakes backwards compatibility with existing kotlin sources:
    class Func: () -> Unit by { someCode() } would not compile anymore
    -> who used this
  • Looks odd with class body because of too many braces
  1. lazy keyword
    Usable before the object you delegate to
    Example:
    class VirtualComponent by lazy getComponent ()
    Pros:
  • Does what I want :slightly_smiling_face:
  • Does not break backwards compatibility
    Cons:
  • Not very general
  • Bad name for the keyword because it does not describe what it does

Currently I’m in favor of the first one because it’s the most general.
I would love to hear from you what you think about and if you think that there are more use cases for interface
delegation to delegates.


#2

I’m not sure if this will solve your problem. There is currently a KEEP about improving interface delegates.

You might want to take a look at it and also leave your feedback there.

AFAIK it’s not approved by the Kotlin team yet so it will probably take some time for it to be implemented but more feedback and maybe a thumbs up won’t hurt.


#3

Sorry and thank you. I didn’t know the topic.
Do you think I should delete my new topic?


#4

Nah leave it. Maybe other people look for the same thing and find it here. In my experience it’s not easy to find a KEEP you don’t know exists.