抽象类与Lambda参数

时间:2016-08-09 08:57:10

标签: oop inheritance lambda abstract kotlin

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

我认为这更简洁,特别是因为val类型得到了推断。

这有什么缺点?

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 个答案:

答案 0 :(得分:3)

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

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

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

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

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

  5. 当尝试考虑运行时开销时,代码在使用抽象函数时看起来并没有太大的不同,消除了运行时开销,并且当前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() {
            /* ...*/
        }
    }