I am not sure how to describe my question , see this code below
sealed class Animal(val type: String) {
data class Cat(val color: String) : Animal("cat")
data class Dog(val mood: String , val ownersName : String) : Animal("dog")
}
abstract class AnimalDescriptor<out T : Animal>(val a: T) {
abstract fun getSummary(): String
}
class CatDescriptor(a: Animal.Cat) : AnimalDescriptor<Animal.Cat>(a) {
override fun getSummary(): String {
return "The color of this ${a.type} is ${a.color}"
}
}
class DogDescriptor(a : Animal.Dog) : AnimalDescriptor<Animal.Dog>(a) {
override fun getSummary(): String {
return "${a.ownersName}'s ${a.type} is ${a.mood}"
}
}
fun main(args: Array<String>) {
fun summary(a : Animal) : String {
return when(a) {
is Animal.Cat -> CatDescriptor(a)
is Animal.Dog -> DogDescriptor(a)
}.getSummary()
}
val kitten = Animal.Cat("yellow")
val doggy = Animal.Dog("happy" , "John")
println(summary(kitten))
println(summary(doggy))
}
The output is
The color of this cat is yellow
John's dog is happy
It works as I want.
But I feel a little ‘fishy’ , because the duplicated type declaration in the initialization of AnimalDescriptor :
class CatDescriptor(a: Animal.Cat) : AnimalDescriptor<Animal.Cat>(a)
It duplicates Animal.Cat here. Is there any way to eliminate any of this ?
Moreover , it cannot forbid us writing this class :
class ADescriptor(a : Animal) : AnimalDescriptor<Animal>(a) {
override fun getSummary(): String {
return "type = ${a.type} "
}
}
Which is meaningless in this case… Is there a better design ?
(functional style or even Kategory incorporation is welcome)