Deal with heritage in Kotlin


#1

Hi all,

I have a question about dealling with heritage with kotlin.
In my Use case,
In my domain I’m dealling with events. This is my model

interface IDomainEvent 
data class WarriorCreated(val content: String): IDomainEvent
data class WarriorDeleted(val content: String = ""): IDomainEvent

In my app, when the user command to delete a ‘warrior’, a WarriorDeleted is created, publish and apply :

 fun delete(publisher: IEventPublisher) {
    if (!projection.isDeleted()) {
        val evt =  WarriorDeleted()
        publisher.publish(evt)
        projection.apply(evt)
    }
}

I would like to create a more generic method like to publish and apply an event

like this for example

 fun delete(publisher: IEventPublisher) {
    if (!projection.isDeleted()) {
        publishAndApplyEvent(publisher, WarriorDeleted())
    }
}

fun publishAndApplyEvent(publisher: IEventPublisher, evt: IDomainEvent) {
    publisher.publish(evt)
    projection.apply(evt)
}

And I created these 2 methods apply :

fun apply(evt: WarriorDeleted) {
    deleted = true
}

fun apply(evt: WarriorCreated) {

}

In this case I have a compilation error : kotlin can’t find the good method appy() depending of the of IDomainEvent.

Is there an easy way for kotlin to find the good method ?

Thanks,


#2

Another limitation of the JVM. What you are asking for is technically called Multiple Dispatch, which is the ability to choose a method to call based on a runtime type and is not supported on the JVM.

Double dispatch is a mechanism that is often used to support a limited workaround for the lack of multiple dispatch. The visitor pattern from GoF is a standard implementation of double dispatch and might be a fit in this case.


#3

I was afraid that someone will answer that.
Yes the visitor pattern can do that.
I was looking for something more simple and automatic.
Apparently I was dreaming to do that on the JVM ^^.

For now I’m using the kotlin when

fun <T : IDomainEvent>publishAndApplyEvent(publisher: IEventPublisher, evt: T) {
    publisher.publish(evt)
    when(evt) {
        is WarriorCreated -> projection.apply(evt)
        is WarriorDeleted -> projection.apply(evt)
    }
}

Thanks for your answer :slight_smile: