簡體   English   中英

從 function 返回匿名 object 並推斷 Kotlin 中的類型

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM