2016-08-18 101 views
3

我有幾個data class與領域,這是在形式使用,需要他們有一個方法的返回true如果任何字段被填滿。聯盟類型/擴展接口

我不想改寫這個對所有的類,所以我做這樣的時刻:

data class Order(var consumer: String, var pdfs: List<URI>): Form { 

    override val isEmpty(): Boolean 
     get() = checkEmpty(consumer, pdfs) 
} 

data class SomethingElse(var str: String, var set: Set<String>): Form { 

    override val isEmpty(): Boolean 
     get() = checkEmpty(str, set) 
} 


interface Form { 
    val isEmpty: Boolean 

    fun <T> checkEmpty(vararg fields: T): Boolean { 
     for (f in fields) { 
      when (f) { 
       is Collection<*> -> if (!f.isEmpty()) return false 
       is CharSequence -> if (!f.isBlank()) return false 
      } 
     } 
     return true; 
    } 
} 

這顯然不是很漂亮,也沒有類型安全。

什麼這樣做,沒有每個屬性抽象成某種Field型的更習慣的方法?

澄清:我正在尋找一種方式,提供所有允許的類型(StringIntListSet),併爲每一個函數來告訴我們,如果他們得到詳盡when,例如空。就像使用方法isEmptyFormField的「擴展接口」一樣。

回答

2

如果你正在做的是檢查isEmpty/isBlank/isZero/etc。那麼你可能不需要一個通用的checkEmpty函數等等。:

data class Order(var consumer: String, var pdfs: List<URI>) : Form { 
    override val isEmpty: Boolean 
     get() = consumer.isEmpty() && pdfs.isEmpty() 
} 

data class SomethingElse(var str: String, var set: Set<String>) : Form { 
    override val isEmpty: Boolean 
     get() = str.isEmpty() && set.isEmpty() 
} 

interface Form { 
    val isEmpty: Boolean 
} 

但是,如果你實際上是做一些更復雜一點,然後根據你的額外澄清我相信「每個屬性抽象成某種Field型」是你想要什麼就是不使每個data classField實例一部分,而是爲它們創建一個列表需要的時候:

data class Order(var consumer: String, var pdfs: List<URI>) : Form { 
    override val fields: List<Field<*>> 
     get() = listOf(consumer.toField(), pdfs.toField()) 
} 

data class SomethingElse(var str: String, var set: Set<String>) : Form { 
    override val fields: List<Field<*>> 
     get() = listOf(str.toField(), set.toField()) 
} 

interface Form { 
    val isEmpty: Boolean 
     get() = fields.all(Field<*>::isEmpty) 

    val fields: List<Field<*>> 
} 

fun String.toField(): Field<String> = StringField(this) 
fun <C : Collection<*>> C.toField(): Field<C> = CollectionField(this) 

interface Field<out T> { 
    val value: T 
    val isEmpty: Boolean 
} 

data class StringField(override val value: String) : Field<String> { 
    override val isEmpty: Boolean 
     get() = value.isEmpty() 
} 

data class CollectionField<out C : Collection<*>>(override val value: C) : Field<C> { 
    override val isEmpty: Boolean 
     get() = value.isEmpty() 
} 

這給你不改變你的data class組件等類型安全,並允許你「獲得詳盡的when「。

+0

仍然不完全滿意,因爲它非常冗長,但我會接受這個答案。謝謝。 –

3

這是有點hacky,但應該工作。 每個data class都會爲每個構造函數參數創建一組方法。它們被稱爲componentN()(其中N是從1開始的指示構造函數參數的編號)。

你可以把這種方法在你的界面,使data class隱式實現它們。見下面的例子:

data class Order(var consumer: String, var pdfs: List) : Form 

data class SomethingElse(var str: String, var set: Set) : Form 

interface Form { 
    val isEmpty: Boolean 
     get() = checkEmpty(component1(), component2()) 

    fun checkEmpty(vararg fields: T): Boolean { 
     for (f in fields) { 
      when (f) { 
       is Collection -> if (!f.isEmpty()) return false 
       is CharSequence -> if (!f.isBlank()) return false 
      } 
     } 
     return true; 
    } 

    fun component1(): Any? = null 
    fun component2(): Any? = null 
} 

您還可以添加fun component3(): Any? = null等等......在data class(如NullObject模式超過2場或搬運null小號直接在checkEmpty()方法

正如我辦案。說,它有點哈克但也許會爲你工作

+0

不錯的主意。您也可以使用反射來列出組件函數,而不是創建可爲空的componentN方法。 – mfulton26

+0

這是一個好主意,但是我正在尋找的是一種讓''時間'盡力而爲的方法。例如。提供如何判斷任意類型是否爲「空」的功能。 (用於字符串的'isBlank()',用於集合的'isEmpty()')... –

1

您可以使用null表示「不確定」。

data class Order(var consumer: String?, var pdfs: List<URI>?) : Form { 
    override val isEmpty: Boolean 
     get() = checkEmpty(consumer, pdfs) 
} 

data class SomethingElse(var str: String?, var set: Set<String>?) : Form { 
    override val isEmpty: Boolean 
     get() = checkEmpty(str, set) 
} 

interface Form { 
    val isEmpty: Boolean 
    fun <T> checkEmpty(vararg fields: T): Boolean = fields.all { field -> field == null } 
} 

這裏的想法是一樣的,在Java中,但沒有額外的對象的Optional<T>的等

現在,您不必擔心null safety但如果你的領域是爲了有缺失/空的一個概念,然後這似乎是適當的(UsingAndAvoidingNullExplained · google/guava Wiki)。

+0

這樣我就會在使用這些類的代碼中失去很多無效安全性。我不得不記得當它們爲空時將'List'設置爲null,等等...... –