摘要 Class 与 Lambda 参数
Abstract Class vs. Lambda parameters
由于 kotlin 对 lambda 的支持如此之好,我开始使用 lambda 作为 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
的引用,这仍然是额外的 运行 时间开销(尽管是微不足道的,除非您有许多这些类型的实例).
Function types 例如 (T) -> Set<String>
可能有命名参数(例如 (element: T) -> Set<String>
)但目前 IDE 如 IntelliJ IDE A 不要在生成的文档或代码存根中使用这些命名参数,因此在子类化等时此类信息会丢失。IDEs 确实在生成的文档和代码存根中使用命名参数作为抽象函数。
您不能(目前)将文档直接与您可以使用抽象函数执行的函数类型参数相关联。
当尝试考虑 运行 时间开销时,代码在使用抽象函数时看起来并没有太大不同,消除了 运行 时间开销,并且当前 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() {
/* ...*/
}
}
由于 kotlin 对 lambda 的支持如此之好,我开始使用 lambda 作为 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
的引用,这仍然是额外的 运行 时间开销(尽管是微不足道的,除非您有许多这些类型的实例).Function types 例如
(T) -> Set<String>
可能有命名参数(例如(element: T) -> Set<String>
)但目前 IDE 如 IntelliJ IDE A 不要在生成的文档或代码存根中使用这些命名参数,因此在子类化等时此类信息会丢失。IDEs 确实在生成的文档和代码存根中使用命名参数作为抽象函数。您不能(目前)将文档直接与您可以使用抽象函数执行的函数类型参数相关联。
当尝试考虑 运行 时间开销时,代码在使用抽象函数时看起来并没有太大不同,消除了 运行 时间开销,并且当前 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() {
/* ...*/
}
}