Search code examples
kotlindelegation

Kotlin class delegation, passing this to delegate


Is there any possibility to pass this when delegating class in kotlin?

class SomeFlow : Flow, SmsAuthentication by DefaultSmsAuthentication(this)

It says this does not exist in this context. The other class looks like this:

class DefaultSmsAuthentication(val flow: Flow) : SmsAuthentication

Solution

  • How about injecting this by setter, not by constructor?

    For example:

    interface SmsAuthentication {
    
        fun withFlow(flow: Flow)
    
        fun auth()
    
    }
    
    class DefaultSmsAuthentication() : SmsAuthentication {
    
        var flow: Flow? = null
    
        override fun withFlow(flow: Flow) {
            this.flow = flow
        }
    
        override fun auth() {
            flow?.proceed()
        }
    
    }
    
    class SomeFlow : Flow, SmsAuthentication by DefaultSmsAuthentication() {
    
        init {
            withFlow(this)
        }
    
    }
    

    However, you need to call withFlow() in constructor by hand every time. You may forget to call it.

    You may want to have SmsAuthentication as a property. So you just inject it by lazy and call it in need. I think it's safer way.

    class SomeFlow : Flow, SmsAuthentication {
    
        val auth by lazy { DefaultSmsAuthentication(this) }
    
        override fun auth() {
            auth.auth()
        }
    
    }
    

    You can also apply Decorator pattern, conversely:

    class DefaultSmsAuthenticationFlow(val flow: Flow) :
        SmsAuthentication,
        Flow by flow
    {
        override fun auth() {
            // you can use flow as this here
        }
    }
    
    fun doAuth(flow: Flow) {
        DefaultSmsAuthenticationFlow(flow).auth()
    }