[英]Kotlin: Generic function as return type?
在 Kotlin 中,是否可以將泛型函數類型聲明為函數的返回類型?
我想要實現的在 Java 中看起來像這樣:
interface Factory {
static Factory INSTANCE = new FactoryImpl();
<T> T create(String name, Class<T> type);
}
class PrefixedFactory implements Factory {
private final String prefix;
PrefixedFactory(String prefix) {
this.prefix = prefix;
}
@Override
public <T> T create(String name, Class<T> type) {
return Factory.INSTANCE.create(prefix + name, type);
}
}
(請注意,在示例中,我使用靜態字段訪問 Factory 實例以避免將泛型函數作為參數傳遞,這會在 Kotlin 中出現其自身的問題)。 我想將前綴轉換為 kotlin 函數,但似乎不可能將泛型函數聲明為返回類型:
fun prefixer(prefix: String): <T> (String, KClass<T>) -> T { TODO() }
這當然不能編譯。 在我看來,與 Java 的功能接口相比,這是一個限制。 有沒有辦法做到這一點,或解決方法?
我希望實際結果函數是通用的。 如果我這樣做
fun <T: Any> prefixer(prefix: String): (String, KClass<T>) -> T { TODO() }
正如目前的答案所暗示的那樣; 我沒有得到通用函數,而是得到(String, KClass<Foo>) -> Foo
如果我調用prefixer<Foo>("")
。 所以這個函數只能用Foo
調用,而在這種情況下工廠函數prefixer
是通用的,結果不是。 我希望能消除誤解。
我的用例是在 Gradle 插件中,我在其中編寫了一個類似於此的輔助方法,該方法將一些默認值應用於創建的每個任務:
val myPrefix = "..."
val project: Project = <from context>
fun <T: Task> String.task(type: KClass<T>, doConfig: T.() -> Unit) {
project.tasks.create("$prefix$this", type.java, { it.doConfig() })
}
請注意,該項目以關閉形式出現。 現在我想在不同的插件中重用該助手,所以我想使用工廠為不同的項目實例創建這個函數。
你幾乎做對了。 您只需要直接在prefixer
函數中定義泛型部分即可。
fun <T: Any> prefixer(prefix: String): (String, KClass<T>) -> T { TODO() }
根據您的實際實現,您可以查看reified
關鍵字。
以下行確實編譯:
fun <T : Any> prefixer(prefix: String): (String, KClass<T>) -> T = TODO()
首先,通用減速應該緊跟在 fun 關鍵字之后。
然后它必須聲明為 Any 類型。 默認是任何? 但 KClass 只接受 Any。
盡管我對閱讀@Alexey 的回答感到失望,但我發現了一種利用 Kotlin 運算符的更簡化的解決方法。 以下使它在使用時看起來更像一個 lambda:
private class Prefixer(private val: String) {
operator fun <T> invoke(name: String, type: Class<T>): T {
TODO()
}
}
要使用它:
val createMy = Prefixer("MyPrefix")
val result = createMy("Configuration", Configuration::class.java)
如有必要,請隨意替換為KClass
。 我實際上是為了稍微不同的目的使用它。
不,這是不可能的(據我所知)。 這種類型的技術術語是“高級類型”,很少有語言支持它們,在 JVM 上我只知道 Scala。
如果有人在沒有像Factory
這樣的界面的情況下問我同樣的問題,我建議完全創建這個界面作為解決方法。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.