我目前正在学习Kotlin,正在学习By Example Guide米.在函数/高阶函数一章中,通过以下示例说明了函数本身如何返回函数:

fun operation(): (Int) -> Int {                                    
    return ::square
}

fun square(x: Int) = x * x                                         

fun main() {
    val func = operation()                                          
    println(func(2))                                               
}

因为我以前已经学习了判断"When"块中变量的类型,所以我try 在这里做同样的事情.判断变量是否为函数类型.

fun operation(): (Int) -> Int {                                   
    return ::square
}

fun square(x: Int) = x * x                                       

fun main() {
    val func = operation()                                        
    when (func){
        is fun -> println(func(2))
        else -> println("Not a function")
    }                                              
}

但这抛出了一个错误"Type Expect",我猜是因为Fun本身不是一种类型.

我试着搜索"Kotlin判断变量是否为函数",但我在哪里找到的都是关于如何判断原语或类的指南,甚至没有提到函数.

推荐答案

让我们假设你对func一无所知.(func是类型Any)您可以通过执行以下操作轻松地判断它是否为函数:

if (func is Function<*>) {
    ...
}

或者类似地在when分支中使用is Function<*>.

但是,这不会告诉您参数的数量或类型,也不会告诉您返回类型.由于您希望在这里使用Int调用函数,因此还必须判断该函数是否恰好有一个Int类型的参数.您可以在单词Function之后添加一个数字来判断特定数量的参数,

if (func is Function1<*, *>) {
    ...
}

但简单的事情就到此为止了.

判断参数类型非常困难.您不能这样做:

if (func is Function1<Int, Int>) {
    ...
}

因为泛型是erased,所以运行库无法区分Function1<Int, Int>Function1<Foo, Bar>,因此您不能使用is判断特定的类型参数.

不幸的是,我能想到的唯一方法就是反思.

// JVM only
if (func is Function1<*, *> && 
    (func as? KFunction<*> ?: func.reflect())?.parameters?.singleOrNull()?.type == typeOf<Int>()) {
    // this is an unchecked cast, which means the runtime won't check it
    // but it is fine, because the code above checked it
    println((func as Function1<Int, *>)(2))
}

operation可以返回KFunction,就像您的::square一样,也可以返回lambda.如果它返回lambda,则使用reflect实验API(您需要@OptIn(ExperimentalReflectionOnLambdas::class))将其转换为KFunction.

在我们有一个KFunction之后,我们可以判断它的单个参数(如果它有一个),并判断它是否为Int.

因此,判断特定类型的函数是一件相当痛苦的事情.如果您发现自己需要这样做,我建议您更改您的设计以避免这样做.

Kotlin相关问答推荐

如何在Kotlin中模拟www.example.com()?

如何优雅地声明一个StateFlow?

有没有什么方法或算法可以在没有存储的情况下生成唯一的随机数?

有什么方法可以要求在 kotlin 中的类型参数上进行注释?

如何在 Kotlin 中将with代码转换为完整代码?

关于 Kotlin 函数类型转换的问题

这是什么 Kotlin 类型:(String..String?)

在 kotlin 中模拟伴随对象函数

在 Kotlin 中使用 @Parcelize 注释时如何忽略字段

Android 在将 androidx 生物识别更新为 1.0.0-alpha04 后崩溃

kotlin 扩展属性的惰性初始化器中的这个引用

致命错误 LifecycleOwners 必须在 registerForActivityResult 开始之前调用 register

如何在 Kotlin 中判断数组类型(不是泛型类型)

Kotlin not nullable值可以为null吗?

使用Dagger 2提供函数依赖性

类型不匹配:推断类型为 LoginActivity 但应为 LifecycleOwner

生成Kotlin类图

如何在Android Studio 4.1中默认启用Kotlin Android扩展

内联 Kotlin 方法没有覆盖报告

我应该在哪里调用 MobileAds.initialize()?