Panda World
Panda World

Reputation: 1996

Kotlin Delegation how to access class properties from delegate object

I'm trying to split some work from a giant class to provide more readability. Firstly I looked into Extension but seems like it is just creating some static functions, then delegate pattern came into my eyes.

The below code looks all right, and delegate works as if part of EnhancedProducer class. But there is one problem that blocking me though, I don't quite get how to access the service property of EnhancedProcuder class from delegate. In my real code, there are some cases that both the original class and delegate class need to use the service variable at the same time, so I don't know if there is a way to do it.

I do understand we can probably inject service instance into both of them but I still want to find out if there is a more elegant way to makes delegate fit into EnhancedProducer class more naturally.

interface Producer {

    fun produce()
}

class ProducerImpl : Producer {

    override fun produce() {
       // service.doSomething() how to access service here
       println( "ProducerImpl")
    } 
}

class EnhancedProducer(private val delegate: Producer) : Producer by delegate {

    // how to share this with delegate 
    //private val service = Service() 

    fun test() {
        produce()
    }
}

fun main() {
    val producer = EnhancedProducer(ProducerImpl())
    producer.test()
}

Upvotes: 2

Views: 1230

Answers (2)

Panda World
Panda World

Reputation: 1996

I have eventually come up with a solution that initialise ProducerImpl right after by keyword. It is so weird that all the examples that I found so far only try to inject an instance rather than providing an initialization when delegation is needed. Maybe someone knows anything about it?

interface Producer {

    fun produce()
}

class ProducerImpl(val service:Service) : Producer {

    override fun produce() {
        service.doSomething()
        println(item)
    }
}

class EnhancedProducer(val service:Service) : Producer by ProducerImpl(service) {
    fun test() {
        produce()
    }
}

fun main() {
    val service = Service()
    val producer = EnhancedProducer(service)
}

Upvotes: 3

alexrnov
alexrnov

Reputation: 2534

May use open properties in the interface:

interface Producer {
    fun produce()
    // two classes will use/modify this property 
    var service: Service 
}
...
class ProducerImpl: Producer {
    override var service = Service()

    fun changeService() {
        service.execute() // access to the interface field
    } 
}
...
class EnhancedProducer(private val delegate: Producer): Producer by delegate {
    fun test() {
        this.service // access to the interface field
        delegate.service // access to the interface field
        produce()
    }
}

fun main() {
    val producerImpl = ProducerImpl()
    val producer = EnhancedProducer(producerImpl)
    producerImpl.service // access to the interface field
    producer.service // access to the interface field
}

Upvotes: 0

Related Questions