简体   繁体   English

Kotlin中的通用Lambda或函数值类型

[英]Generic lambda or function value type in Kotlin

Given a function 给定功能

fun <T> to5(x: T): Int = 5

is it possible to assign it to variable (value) funVal like this ? 是否可以像这样将其分配给变量(值) funVal

val funVal: (T) -> Int = ::to5

without 没有

Unresolved reference: T 未解决的参考:T

error ? 错误?

In other words is it possible to somehow tell Kotlin that T in funVal type declaration is a type parameter? 换句话说,是否可以以某种方式告诉Kotlin, funVal类型声明中的T是类型参数?

For example like this: 例如这样:

val <T> funVal: (T) -> Int = ::to5

val funVal<T>: (T) -> Int = ::to5

val funVal: <T> (T) -> Int = ::to5

val funVal: ((T) -> Int) <T> = ::to5

Use case 用例

My use case is using currying with generics. 我的用例是对泛型使用currying。 Conceptually: 从概念上讲:

    fun pairStrWithStr(s: String): (String) -> Pair<String, String> = {
        Pair(s, it)
    }

    val pairStrWithAbc: (String) -> Pair<String, String> = pairStrWithStr("abc")

    pairStrWithAbc("xyz") // (abc, xyz)

Making the second argument generic: 使第二个参数通用:

fun <T> pairStrWithAny(s: String): (T) -> Pair<String, T> = {
    Pair(s, it)
}

// Compilation ERROR: Unresolved reference: T
val pairAnyWithAbc: (T) -> Pair<String, T> = pairStrWithAny("abc")

Of course I can provide Any as type: 当然,我可以提供Any作为类型:

val pairAnyWithAbc: (Any) -> Pair<String, Any> = pairStrWithAny("abc")

But then I lose the type information: 但是然后我丢失了类型信息:

pairAnyWithAbc(5) // Pair<String, Any>

The solution I can think of are: 我能想到的解决方案是:

Wrapping inside generic fun (basically not real currying or high order function usage) 包装通用乐趣 (基本上不是真正的curry或高阶函数的用法)

 fun <T> pairAnyWithAbc(t: T) {
        return pairAnyWithAbc(t)
 }

Creating function for each type (no using generics as I would like) 为每种类型创建函数 (我不希望使用泛型)

val pairStrWithAbc: (String) -> Pair<String, String> = pairStrWithAny("abc")

val pairIntWithAbc: (Int) -> Pair<String, Int> = pairStrWithAny("abc")

Only classes and functions can have generic type parameters in Kotlin. Kotlin中只有类和函数可以具有泛型类型参数。 If you really need a property to have a generic type, it has to belong to a class instance that can provide that generic type, like so: 如果确实需要某个属性具有泛型类型,则它必须属于可以提供该泛型类型的类实例,如下所示:

class Foo<T> {
    val funVal: (T) -> Int = ::to5
}

There's more discussion about this here , I just can't flag this as a duplicate because that question doesn't have an accepted answer. 有一个关于这个更多的讨论在这里 ,我只是不能将此作为一个重复的,因为这个问题没有一个公认的答案。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM