Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Exhaustive when statement with sealed interface not working with MappedSuperclass, Entity and sealed interface

I have this MappedSuperClass

@MappedSuperclass
abstract class BaseFoo(
    ...
) : FooItem {
    ...
}

sealed interface FooItem

Which is then used like this

@Entity
@Table(name = "bar_1")
class Bar1(
    ...
) : BaseFoo(
    ...
) { ... }


@Entity
@Table(name = "bar_2")
class Bar2(
    ...
) : BaseFoo(
    ...
) { ... }


@Entity
@Table(name = "all_bar")
class AllBar(
    ...

    @OneToMany(mappedBy = "all_bar", fetch = FetchType.LAZY, cascade = [CascadeType.REMOVE])
    val bar1: List<Bar1>? = null,

    @OneToMany(mappedBy = "all_bar", fetch = FetchType.LAZY, cascade = [CascadeType.REMOVE])
    val bar2: List<Bar2>? = null,
) {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    var id: Long = 0

    val barItems: List<FooItem>
        get() = listOfNotNull(bar1, bar2).flatten()
}

I then want to add an exhaustive when statement

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

val bars = allBarRepository.findById(someId).getOrElse {...}
bars.barItems.forEach {
    when (it) {
        is Bar1 -> ...
        is Bar2 -> ...
    }

But the compiler says

‘when’ expression must be exhaustive, add necessary ‘is BaseFoo’ branch or ‘else’ branch instead

I do not want to check for BaseFoo, but only for Bar1 and Bar2 and if there will be more Bar_<INT> for all the other Bars that will be added in the future. I want the compiler to complain when I forget to add any of Bar_<INT> here. By either adding an else branch or checking for BaseFoo this won’t work anymore. I thought this is what sealed interfaces can be used for?

>Solution :

BaseFoo should also be sealed.

sealed class BaseFoo(
    ...
) : FooItem {
    ...
}

sealed classes are implicitly abstract, but classes that are only abstract are not sealed. They "open" the hierarchy, and there could be other classes that inherit from BaseFoo.

A bit off topic, but Java’s sealed interfaces/classes require you to specify whether each subclass is sealed/non-sealed/final. I would recommend keeping that in mind when writing Kotlin too. non-sealed would correspond to having no modifier in Kotlin.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading