在Kotlin中,是否可以将泛型函数类型声明为函数的返回类型?
我想要实现的目标在Java中看起来像这样:
case class Product(
@(QuerySqlField @field)(index = true) version: Long,
attributes: java.util.Map[String, String]
)
object Main {
val TestProduct = Product(2L, Map("pid" -> "123", "foo" -> "bar", "baz" -> "quux").asJava)
def main(args: Array[String]): Unit = {
Ignition.setClientMode(true)
val ignite = Ignition.start()
val group = ignite.cluster.forServers
val cacheConfig = new CacheConfiguration[String, Product]
cacheConfig.setName("inventory1")
cacheConfig.setIndexedTypes(classOf[String], classOf[Product])
val cache = ignite.getOrCreateCache(cacheConfig)
cache.put("P123", TestProduct)
val query = new SqlQuery(classOf[Product], "select * from Product where version > 1")
val resultSet = cache.query(query)
println(resultSet)
}
}
(注意,在示例中,我使用静态字段访问Factory实例,以避免将泛型函数作为参数传递,这将在Kotlin中呈现自己的问题)。 我想将前缀转换为kotlin函数,但似乎不可能将泛型函数声明为返回类型:
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);
}
}
这当然不能编译。在我看来,与Java的功能接口相比,这是一个限制。有没有办法实现这一目标,或者解决方法?
我希望实际的结果函数是通用的。如果我做
fun prefixer(prefix: String): <T> (String, KClass<T>) -> T { TODO() }
目前的答案表明;我没有获得通用函数,而是在调用fun <T: Any> prefixer(prefix: String): (String, KClass<T>) -> T { TODO() }
时获得(String, KClass<Foo>) -> Foo
。因此,只能使用prefixer<Foo>("")
调用该函数,而在这种情况下,工厂函数Foo
是通用的,结果不是。我希望能够消除误解。
我的用例是在Gradle插件中,我写了一个类似于这个的帮助方法,它将一些默认值应用于每个创建的任务:
prefixer
请注意,该项目是封闭式的。现在我想在不同的插件中重用该帮助器,所以我想使用工厂为不同的项目实例创建这个函数。
答案 0 :(得分:3)
你几乎正确地做到了。您只需要直接在prefixer
函数中定义通用部分。
fun <T: Any> prefixer(prefix: String): (String, KClass<T>) -> T { TODO() }
根据您的实际实施情况,您可以查看reified
关键字。
答案 1 :(得分:2)
以下行确实编译:
fun <T : Any> prefixer(prefix: String): (String, KClass<T>) -> T = TODO()
首先,通用减速应该在fun关键字之后。
然后必须将其声明为Any类型。默认是Any?但KClass只接受Any。
答案 2 :(得分:0)
不,这是不可能的(据我所知)。这种类型的技术术语是“更高级的类型”,很少有语言支持它们,在JVM上我只知道Scala。
如果有人在没有像REGISTER_OP("CsvIter")
.Input("data_file: string")
.Output("labels: float32")
.Output("signs: int64")
.Attr("input_schema: list(string)")
.Attr("feas: list(string)")
.Attr("label: string = 'label' ")
.Attr("batch_size: int = 10000")
.SetIsStateful(); // Add this line.
这样的界面的情况下向我提出同样的问题,我建议您准确创建此界面作为解决方法。
答案 3 :(得分:0)
尽管我对阅读@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
替换。实际上,我将其用于稍微不同的目的。