Reputation: 1996
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
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
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