假设我有以下代码:
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 color of this cat is yellow
John's dog is happy
这确实是我想要的。
但我觉得有点“腥”,因为AnimalDescriptor
初始化中的重复类型声明:
class CatDescriptor(a: Animal.Cat) : AnimalDescriptor<Animal.Cat>(a)
此外,它不能禁止我们写这个课:
class ADescriptor(a : Animal) : AnimalDescriptor<Animal>(a) {
override fun getSummary(): String {
return "type = ${a.type} "
}
}
在这种情况下,这是毫无意义的。
有更好的设计吗?
欢迎功能风格甚至Kategory合并。
但至少要保留sealed class
设计。
KotlinConf 2017 这张幻灯片引起了我的注意:
我不确定纯Kotlin(没有其他第3个库的方式)是否可以达到我的要求,但似乎Kategory它可以做到这一点,它是否可能在Kategory?怎么样?
-----更新回复@PaulHicks -----
如果我想在里面做一些AnimalDescriptor
, template
是不可避免的,例如:
abstract class AnimalDescriptor<out T : Animal>(val a: T) {
fun sayHello() : String {
return "Hello : " + getSummary()
}
abstract fun getSummary(): String
}
fun hello(a: Animal): String {
return when (a) {
is Animal.Cat -> CatDescriptor(a)
is Animal.Dog -> DogDescriptor(a)
}.sayHello()
}
val kitten = Animal.Cat("yellow")
val doggy = Animal.Dog("happy", "John")
println(hello(kitten))
println(hello(doggy))
并输出:
Hello : The color of this cat is yellow
Hello : John's dog is happy