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
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?
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.