data class Type1(val str: String)
data class Type2(val str: String)
interface Person
data class Child1(val name: Type1) : Person
data class Child2(val name: Type2) : Person
fun main() {
val foo = Child1(Type1("foo"))
val bar = Child2(Type2("bar"))
printName(foo)
printName(bar)
}
fun printName(person: Person) {
// Option 1: would like to do this
// println(person.name) // Unresolved reference: name
// Option 2: works but if I have lots of other code,
// it's unnecessary duplication of code
when (person) {
is Child1 -> {
println(person.name)
// lots of other code
}
is Child2 -> {
println(person.name)
// lots of other code
}
}
}
Inside printName(), I would like to be able to use a single println(person.name) call and have it print the name of either Child1 or Child2, whichever is passed in. What are the different ways I can make this happen in Kotlin?
UPDATE:
- I don't own the base classes so not able to change the inheritance.
- The names of each child are of different types.
CodePudding user response:
You need to have name
in your interface, like
interface Person {
val name: String
}
data class Child1(override val name: String) : Person
data class Child2(override val name: String) : Person
to be able to get it from other Child classes...
If not every child class that extends Person will contain name, you can introduce an intermediate interface, like
interface Person
interface NamedPerson : Person {
val name: String
}
data class Child1(override val name: String) : NamedPerson
data class Child2(override val name: String) : NamedPerson
In any other case, there should be an instance check, like
when (person) {
is Child1 -> println(person.name)
is Child2 -> println(person.name)
}
CodePudding user response:
You can create an extension function if you don't own those classes
data class Type1(val str: String)
data class Type2(val str: String)
interface Person
data class Child1(val name: Type1) : Person
data class Child2(val name: Type2) : Person
// extension
fun Person.getNameStr() : String {
return when(this){
is Child1 -> name.str
is Child2 -> name.str
else -> ""
}
}
// or
val Person.nameStr : String
get() = when(this){
is Child1 -> name.str
is Child2 -> name.str
else -> ""
}
fun printName(person: Person) {
println(person.getNameStr())
//or
println(person.nameStr)
}
Importance
this extension will not valid if you want to return the class itself (Type1
and Type2
)