https://kotlinlang.org logo
Title
j

jean

01/25/2023, 8:56 AM
Shouldn’t something like this be possible?
sealed class DataTest {
    data class A(val value: String): DataTest()
    data class B(val value: String): DataTest()
    data class C<Type>(val value: Type): DataTest()
}

fun test(dataClass: DataTest.A) = println("A: ${dataClass.value}")
fun test(dataClass: DataTest.B) = println("B: ${dataClass.value}")
fun test(dataClass: DataTest.C<*>) = println("C: ${dataClass.value}")

fun reducer(dataClass: DataTest) = test(dataClass) // compiler complains that there is no test function with parameter DataTest

@Test
fun shouldWork() {
    reducer(DataTest.A("a"))
    reducer(DataTest.B("b"))
    reducer(DataTest.C(0))
}
Since the sealed class defines exactly the number of child for
DataTest
couldn’t the compiler check that there is a
test
function for each child? Instead of implementing a whole visitor pattern
s

Sam

01/25/2023, 9:02 AM
Function overloads are resolved statically (at compile time).
e

ephemient

01/25/2023, 9:03 AM
you could write
fun reducer(dataClass: DataClass) = when (dataClass) {
    is A -> test(dataClass)
    is B -> test(dataClass)
    is C -> test(dataClass)
}
but yeah, as Sam says, the fact that the three functions have the same name is irrelevant
j

jean

01/25/2023, 9:04 AM
I was trying to avoid the
when
🤷🏻
s

Sam

01/25/2023, 9:05 AM
The ability to use
when
is kind of the whole point of a sealed type.
I resisted at first too 😄 my Java background made me think it was a bad idea. But I’ve softened to it. In practice it’s much cleaner and easier to follow than a visitor pattern.
j

jean

01/25/2023, 9:07 AM
I completely agree and use
when
quite often, it was more of a theoretical wonder
c

CLOVIS

01/25/2023, 9:08 AM
It's important for readability that a single place in code calls a single function, and it doesn't depend on the value of the argument. The exception of course is inheritance, but this is very well delimited (it can only happen based on the receiver, functions must be marked
abstract
or
open
to allow it, etc)
s

Sam

01/25/2023, 9:09 AM
I mean, multiple dispatch is a thing, Kotlin just doesn’t have it…
j

jean

01/25/2023, 9:10 AM
I was wondering this because C looses the type due to erasure, so I can’t get a
when
statement for C with this
is C<String> -> ...
is C<Int> -> ...
c

CLOVIS

01/25/2023, 9:11 AM
Kotlin has type erasure too, but that's only for type parameters. A sealed class is a proper inheritance hierarchy, there is no type erasure there
e

ephemient

01/25/2023, 9:11 AM
`as`/`is` can only check the erased type (except for
Array<>
, for somewhat historical Java reasons)