juliocbcotta
01/27/2024, 12:29 PMephemient
01/27/2024, 12:53 PMsealed interface Foo
fun foo(foo: Foo): Any = when (foo) {
}
which is compiled first, then module 2
class Bar : Foo
which is compiled later, then the code in module 1 is brokenjuliocbcotta
01/27/2024, 12:59 PMephemient
01/27/2024, 1:00 PMjuliocbcotta
01/27/2024, 1:00 PMephemient
01/27/2024, 1:01 PMjuliocbcotta
01/27/2024, 1:03 PMjuliocbcotta
01/27/2024, 1:05 PMjuliocbcotta
01/27/2024, 1:25 PMAdam S
01/27/2024, 1:25 PMephemient
01/27/2024, 1:26 PMsealed
juliocbcotta
01/27/2024, 1:26 PMjuliocbcotta
01/27/2024, 1:27 PMephemient
01/27/2024, 1:28 PMjuliocbcotta
01/27/2024, 1:36 PMwhen
is that it needs to know "all subclasses/interfaces in the sealed hierarchy", right ? That info is available at any module that can read that sealed interface. The rule applies at the definition of the sealed hierarchy, not at the client.Adam S
01/27/2024, 1:49 PMlibrary
and application
(which depends on library
)
In library
you have a sealed interface, and some function that performs some operation on the sealed interface.
// library/src/main/kotlin/lib.kt
sealed interface MyData
interface AlphaData : MyData
interface BetaData : MyData
fun libOperation(data: MyData) {
val name = when (data) {
is AlphaData -> "alpha"
is BetaData -> "beta"
}
println("libOperation got data $name")
}
And then in application
you're proposing that a new implementation is allowed.
// application/src/main/kotlin/app.kt
interface GammaData: MyData
So a similar operation function in application
can use a when + the sealed interface
// application/src/main/kotlin/app.kt
fun appOperation(data: MyData) {
val name = when (data) {
is AlphaData -> "alpha"
is BetaData -> "beta"
is GammaData -> "gamma"
}
println("appOperation got data $name")
}
And then let's say that the application's main function calls both the library operation, and the application's operation
// application/src/main/kotlin/app.kt
fun main() {
val data = object : GammaData {}
libOperation(data)
appOperation(data)
}
But the library function doesn't know about GammaData
because it was defined in another module. What should happen? Throw an error? But then the usefulness of the when
statement is weakened.juliocbcotta
01/27/2024, 1:59 PMMyData
. The interfaces that could (should) be allowed to be implemented in another module are the "children" interfaces. Or if the parent interface is allowed to be implemented, it should be by another sealed class/interface.juliocbcotta
01/27/2024, 2:02 PMAdam S
01/27/2024, 2:07 PMMyData
open and adding an else -> {}
branch on the when statementsAdam S
01/27/2024, 2:12 PMsealed interface MyData
interface AlphaData : MyData {
val string: String
}
interface BetaData : MyData {
val bool: Boolean
}
interface GammaData : MyData {
val int: Integer
}
And then you can implement the subtypes in the same module, or another module.
data class AlphaDataImpl(override val string: String) : AlphaData
data class BetaDataImpl(override val bool: Boolean) : BetaData
data class GammaDataImpl(override val int: Integer) : GammaData
juliocbcotta
01/27/2024, 2:16 PMjuliocbcotta
01/27/2024, 2:17 PMRob Elliot
01/27/2024, 3:12 PMpackage module1
sealed interface MyInterface
interface ChildA : MyInterface
interface ChildB : MyInterface
fun main() {
val x: MyInterface = TODO()
val result: Int = when (x) {
is ChildA -> 1
is ChildB -> 2
}
}
`module2`:
package module2
import module1.ChildA
import module1.ChildB
class GrandChildA1 : ChildA
class GrandChildA2 : ChildA
class GrandChildB1 : ChildB
class GrandChildB2 : ChildB
Obviously you can't have a direct child of MyInterface
in module2
, because then what would x
be in `module1`'s main
method?juliocbcotta
01/27/2024, 8:31 PM