[英]Returning anonymous object from function and infering type in Kotlin
我來自 Java 並且是 Kotlin 的新手。 我正在嘗試為單元測試目的創建聲明性 DSL。 這是我嘗試創建通用構建器方法以使用聲明性語法構造任何 model object。
fun <T> having(t: Class<T>) = object {
infix fun with(fn: T.() -> Unit) = t.newInstance().apply(fn)
}
fun test() {
having(Pizza::class.java) with {
size = Size.NORMAL
cheese = Cheese.MOZARELLA
}
}
但是, having
function 將返回with
未解析引用的Any
類型 function。 我可以將匿名的 object 提取到它自己的 class 以使其編譯,但它會感覺多余。 是否可以使用返回object
實例的函數來進行類型推斷?
另外,我不確定我是否在這里使用 generics 的慣用方式。
我在此處的回答中解釋了having
函數的返回類型推斷為Any
的原因。 基本上,您必須將having
設為private
才能使其推斷出所需的返回類型。 顯然,這對於您單元測試 DSL 來說不是一個可行的解決方案,它將被其他文件中的代碼使用。
您可以考慮刪除單詞 have having
並直接在 KClass 上將with
聲明為擴展/中綴KClass
。
擴展 function:
fun <T: Any> KClass<T>.with(fn: T.() -> Unit) = this.createInstance().apply(fn)
// ...
Pizza::class.with {
size = Size.NORMAL
cheese = Cheese.MOZZARELLA
}
中綴 function:
infix fun <T: Any> KClass<T>.with(fn: T.() -> Unit) = this.createInstance().apply(fn)
fun main() {
Pizza::class with {
size = Size.NORMAL
cheese = Cheese.MOZZARELLA
}
}
Instead of returning an object
of unspecified type, you can return a wrapping object, which declares the with
function and contains the original class object.
通過這種方式,您可以獲得類型安全,同時保持您having
-style DSL。
data class WrappedInstance<T>(val data: T) {
infix fun with(applyFn: T.() -> Unit): T = data.also(applyFn)
}
fun <T : Any> having(kClass: KClass<T>): WrappedInstance<T> =
WrappedInstance(kClass.createInstance())
使用它,看起來像這樣:
data class Pizza(var size: Int = 1, var cheese: Int = 1)
fun test() {
val pizza: Pizza = having(Pizza::class) with {
size = 3
cheese = 5
}
println(pizza.size)
println(pizza.cheese)
}
請注意,這以及您的原始方法都有一個警告。 它們僅適用於具有構造函數的類,不需要任何參數。
請參閱KClass<T>.createInstance()
的文檔:
創建 class 的新實例,調用沒有參數或所有參數都是可選的構造函數(請參閱 KParameter.isOptional)。 如果沒有或很多這樣的構造函數,則拋出異常。
當不需要 DSL having
一部分時,請查看@Sweeper 的解決方案。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.