抽象类与Lambda参数

由于kotlin对lambdas有很好的支持,我开始使用lambdas作为abstract类的构造函数参数,而不是声明abstract val/fun

我认为这更简洁,特别是因为val type 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() { /* ...*/ } } 

  1. 在你的例子中, OrderListScreen每个实例都将创建它自己的函数类型(T) -> Set<String>filterators实例。 与抽象函数及其在编译时存储在类型定义中的重写相比,这会在内存和性能方面产生额外的运行时间开销。
  2. 默认的过滤器可以存储在属性中以减少运行时间的开销:

     class OrderListScreen : AbstractListScreen<Data>(data = setOf(), filterators = defaultFilterators ) { companion object { val defaultFilterators: (Data) -> Set<String> = { setOf(it.toString()) } } fun someEvent() { /* ...*/ } } 

    然而, OrderListScreen每个实例仍然有它自己的引用defaultFilterators这仍然是额外的运行时间开销(尽管边际,除非你有这些类型的许多实例)。

  3. (T) -> Set<String>这样的函数类型可能具有命名参数(例如(element: T) -> Set<String> ),但是当前的IDE如IntelliJ IDEA不会在生成的文档或代码存根中使用这些命名参数因此这样的信息在子类化等时会丢失。IDE在生成的文档中使用命名参数,在抽象函数中使用代码存根。

  4. 您不能(现在)直接将文档与您可以使用抽象函数执行的函数类型参数相关联。

当试图解释运行时间开销时,使用抽象函数时代码看起来并没有什么不同,运行时开销被消除了,当前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() { /* ...*/ } }