kotlinspring-dataspring-data-r2dbcspring-data-commons

How to fix the conflict when implement two id interfaces?


One interface is 'org.springframework.data.domain.Persistable', it's a java interface with a method ID getId() in 3rd-party lib.

Another interface is a Kotlin interface interface IdEntry { val id: String}.

Now my business entry needs to implement these two interfaces:

data class MyEntry(
  override val id: String,
  ....// more properties
) : IdEntry, Persistable<String>

I use IntelliJ IDE to code and the error is:

Class 'MyEntry' is not abstract and does not implement abstract member 
@Nullable public abstract fun getId(): String! 
defined in org.springframework.data.domain.Persistable

How can I fix this?

I also tried below code: (idea from here)

data class MyEntry(
  private val id: String,
  ....// more properties
) : IdEntry, Persistable<String> {
  override fun getId() = id
  ...
}

But this also failed:

Cannot weaken access privilege 'public' for 'id' in 'IdEntry'

Solution

  • This is a platform declaration clash that cannot easily be resolved as long as MyEntry implements both IdEntry and Persistable.

    However, there is one way, if you declare the property that is inherited by IdEntry as a @JvmField:

    import org.springframework.data.domain.Persistable
    
    data class MyEntry(@JvmField override var id: String) :
            IdEntry, Persistable<String> {
    
        override fun getId(): String? = this.id
    
        override fun isNew(): Boolean {
            TODO("not implemented")
        }
    }
    
    interface IdEntry {
        val id: String
    }
    

    This works, because the clash occurs when the Kotlin compiler generates getters and setters for the id property as long as it has no @JvmField annotation.

    The getter clashes with the function getId() inherited from Persistable.

    By adding @JvmField, the generation of the getter for the id from IdEntry is avoided, thus preventing the clash.