You can do it if you have them both implement a common interface, and use the interface as the type of parameter:
interface HasCommon {
val common: String
}
data class A(val a: String, override val common: String) : HasCommon
data class B(val b: String, override val common: String) : HasCommon
fun accept(param: HasCommon) {
println(param.common)
}
fun main() {
accept(A("a", "a"))
accept(B("b", "b"))
}
Output:
a
b
Alternatively, you could do it in a more functional way by defining multiple versions of accept
for each type, and abstracting out the common functionality:
data class A(val a: String, val common: String)
data class B(val b: String, val common: String)
fun accept(a: A) = printCommon(a.common)
fun accept(b: B) = printCommon(b.common)
fun printCommon(common: String) = println(common)
fun main() {
accept(A("a", "a"))
accept(B("b", "b"))
}