我在这里列出了多个选项,其中一些可以组合使用以重用代码并生成最少数量的繁琐代码。
与默认实现的接口
您可以使用具有默认功能实现的接口来提供公共基础:
interface CommonDataInterface<T> {
val commonParam1: String
val commonParam2: String
val specialParam: T
fun foo() { ...implementation here }
fun bar() { ...implementation here }
fun zoo(x: T): T { ...implementation here }
}
// concrete variations, using common interface functions implemented above:
data class A(override val commonParam1: String,
override val commonParam2: String,
override val specialParam: Int)
: CommonDataInterface<Int>
data class B(override val commonParam1: String,
override val commonParam2: String,
override val specialParam: String)
: CommonDataInterface<String>
data class C(override val commonParam1: String,
override val commonParam2: String,
override val specialParam: Boolean)
: CommonDataInterface<Boolean>
data class D(override val commonParam1: String,
override val commonParam2: String,
override val specialParam: Float)
: CommonDataInterface<Float>
使用非数据类扩展基类
另一种方法是非数据类的泛型类:
class G<T>(val commonParam1: String, val commonParam2: String, val specialParam: T) {
fun foo() { ...implementation here }
fun bar() { ...implementation here }
fun zoo(x: T): T { ...implementation here }
}
// concrete variations, using common functions from base class
class A(commonParam1: String, commonParam2: String, specialParam: Int)
: G<Int>(commonParam1, commonParam2, specialParam)
class B(commonParam1: String, commonParam2: String, specialParam: String)
: G<String>(commonParam1, commonParam2, specialParam)
class C(commonParam1: String, commonParam2: String, specialParam: Boolean)
: G<Boolean>(commonParam1, commonParam2, specialParam)
class D(commonParam1: String, commonParam2: String, specialParam: Float)
: G<Float>(commonParam1, commonParam2)
这并没有节省多少打字,而且有很多冗余参数。
使用接口的透明委托
如果您需要将所有内容保留在类中或想要组合多个不同的功能集(您可以实现多个接口并委托给多个支持实现),则另一种方法是使用“委托继承”:
interface CommonDataInterface {
val commonParam1: String
val commonParam2: String
fun foo()
fun bar()
}
data class CommonData(override val commonParam1: String,
override val commonParam2: String)
: CommonDataInterface {
override fun foo() { ...implementation here }
override fun bar() { ...implementation here }
}
// concrete implementations using common functions via automatic delegation
data class A(private val common: CommonDataInterface,
val specialParam: Int) : CommonDataInterface by common {
fun zoo(x: Int): Int { ...implementation here using specialParam }
}
data class B(private val common: CommonDataInterface,
val specialParam: String) : CommonDataInterface by common {
fun other(y: String): String { ...implementation here using specialParam }
}
data class C(private val common: CommonDataInterface,
val specialParam: Boolean) : CommonDataInterface by common
data class D(private val common: CommonDataInterface,
val specialParam: Float) : CommonDataInterface by common
但以上内容不允许specialParam 被任何通用函数使用,它将根据专业化实现。
使用注释处理器生成类的排列
您可以编写自己的注释处理器,这是代码生成或其他编译时操作的一种形式,将注释添加到您的特殊类,并让注释处理器生成字节码中的所有排列。然后它可以融入到你的编译过程中,神奇地出现那些额外的类。
您需要在某处查看 Kotlin 如何进行注释处理以及一般主题。此外,Kotlin 1.4 之后可能会是一个编译器插件 API,它可以帮助编写做类似工作的插件。
注释处理的一些链接表明它并不难处理:
使用 Kotlin 代码生成库生成 Kotlin 代码
查看 Kotlin 代码生成的一个简单方法是 KotlinPoet 库。它是一种以编程方式生成代码的方式,即使对于代码生成经验很少的团队来说也很容易。这可以与前面提到的关于如何构建类的变体一起使用。它也可以与注释处理一起使用,作为在编译期间触发代码生成的方法。