由于kotlin对lambdas有很好的支持,我开始使用lambdas作为abstract
类的构造函数参数,而不是声明abstract val/fun
。
我认为它更简洁,特别是因为val
类型的get是推断出来的。
这样做的缺点是什么?
abstract class AbstractListScreen<T> (
val data: Set<T>,
val filterators: (T) -> Set<String>
) {
fun open() {
/* ... */
}
}
class OrderListScreen : AbstractListScreen<Data>(data = setOf(),
filterators = { setOf(it.toString()) }
) {
fun someEvent() {
/* ...*/
}
}
- 在您的示例中,
OrderListScreen
的每个实例将创建自己的filterators
实例,其函数类型为(T) -> Set<String>
。与编译时存储在类型定义中的抽象函数及其覆盖相比,这在内存和性能方面都有额外的运行时开销。 -
默认过滤器可以存储在属性中以减少此运行时开销:
class OrderListScreen : AbstractListScreen<Data>(data = setOf(), filterators = defaultFilterators ) { companion object { val defaultFilterators: (Data) -> Set<String> = { setOf(it.toString()) } } fun someEvent() { /* ...*/ } }
然而,
OrderListScreen
的每个实例仍然有自己对defaultFilterators
的引用,这仍然是额外的运行时开销(尽管边际,除非您有许多这些类型的实例)。 -
函数类型,如
(T) -> Set<String>
可能有命名参数(如(element: T) -> Set<String>
),但目前ide,如IntelliJ IDEA不使用这些命名参数在生成的文档或代码存根,所以这些信息丢失时,子类化等。ide确实在生成的文档和抽象函数的代码存根中使用命名参数。 -
你不能(目前)直接将文档与函数类型参数相关联,而你可以用抽象函数来做。
当试图考虑运行时开销时,代码在使用抽象函数时看起来并没有太大的不同,运行时开销被消除了,并且当前IDE对生成的代码存根、文档等的支持得到了改进:
abstract class AbstractListScreen<T>(val data: Set<T>) {
abstract fun filterators(element: T): Set<String>
fun open() {
/* ... */
}
}
class OrderListScreen : AbstractListScreen<Data>(data = setOf()) {
override fun filterators(element: Data): Set<String> = setOf(element.toString())
fun someEvent() {
/* ...*/
}
}