2016-08-09 70 views
1

由於科特林有lambda表達式這種良好的支持,我開始使用lambda表達式作爲構造參數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() { 
     /* ...*/ 
    } 
} 

回答

3
  1. 在您的例子中,OrderListScreen每個實例將創建功能型(T) -> Set<String>自身的filterators實例。與抽象函數及其在編譯時存儲在類型定義中的替代函數相比,這會在內存和性能方面增加運行時開銷。
  2. 默認filterators可以存儲在一個屬性來減少這種運行時開銷:

    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. 您不能(現在)直接將文檔與函數類型參數相關聯,您可以使用抽象函數執行該參數。

當試圖佔運行時開銷中的抽象函數時的代碼看起來並不太大的不同,運行時開銷被消除,並生成代碼存根,文檔等目前的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() { 
     /* ...*/ 
    } 
} 
+2

事實上,代碼看起來更清潔,少令人費解;) – voddan

+0

我會接受這個答案,但我希望得到有關OOP和重構(refactorization)的更多信息,而不是實際的(文件和性能)問題... –