美文网首页
函数类型

函数类型

作者: 一江碎月 | 来源:发表于2018-07-25 14:06 被阅读0次

    用于指定该参数接收一个函数或者一个 lambda 表达式。

    声明

    用小括号将参数类型括起来,后跟 ->,最后是返回值类型。如下:

    (Int,String, Int) -> Unit
    

    它表示该函数接收三个参数,类型分别是 int,string,int,返回值类型为 Unit。因此,下面定义的函数可以匹配上述的函数类型:

        fun demo(a: Int, b: String, c: Int) 
    

    函数类型的参数可以接收一个 labmda 或 一个函数成员引用,不能直接将函数名传入其中

    fun main(args: Array<String>) {
        test(::demo)
    
        test { a, b, c ->
            println("$a,$b,$c")
        }
    }
    
    fun test(action: (Int, String, Int) -> Unit) {
        action(3, "aaa", 2)
    }
    
    fun demo(a: Int, b: String, c: Int) {
        println("$a,$b,$c")
    }
    

    函数类型接口

    函数类型是一种类型,因此函数类型可以做为父类,可以定义实现了某个函数类型的类。

    函数类型的子类,必须重写 invoke 方法。该方法的参数类型是函数类型的参数类型,返回值类型是函数类型的返回值类型:

    fun main(args: Array<String>) {
        val t = Test()
        println( t("xxx")) // true
        println(t("yii")) // false
    }
    
    class Test : (String) -> Boolean {
        override fun invoke(p1: String): Boolean = p1.contains("xx")
    }
    

    在编译后,函数类型会转成 Function 的子类,而 Function 中定义了 invoke 方法,所以子类必须实现 invoke 方法。

    而且根据 invoke 约定,可直接使用像调用函数一样调用子类实例。如上述的 t("xxx")。


    实质

    函数类型在编译后都会转成 FunctionN<P1,P2,...,PN,R> 的子类。其中 P1 到 PN 表示函数类型的参数类型,R 表示返回值类型。因此,(T)->R 可以认为是 Function1 类的 kt 写法,两者等价。

    默认值

    函数类型也是一种类型,因此可以用作函数的形参类型。

    kt 的函数中,形参可以指定默认值。因此函数类型的形参也可以指定默认值,其值可以是成员引用,也可以是 lambda:

    fun main(args: Array<String>) {
        println(demo())
        println(demo2())
    }
    
    fun test() = "aa"
    
    fun demo(a: () -> String = { "lambda" }) = a()
    fun demo2(a: () -> String = ::test) = a()
    

    作为参数,表达式有可能为 null,只要对应的变量声明为可空类型。而 java 调用含 lambda 的函数时,在对应的位置上传递的是 FunctionN 的实例。 而 FunctionN 中定义了 invoke 方法,因此可以 结合 FunctionN 与安全调用,避免对参数的空判断

    fun test(a:((Int)->String)?){
        if(a != null)
            println(a(2))
    }
    
    fun test2(a:((Int)->String)?){
        println(a?.invoke(3)) // 直接调用 invoke 方法,相当于执行了表达式
    }
    

    test() 方法中进行空判断,然后调用;test2 中,使用安全调用 invoke 方法。


    在 java 中使用

    在 java 中调用含有函数类型参数的函数时,需要显式地传入一个 FunctionN 的实例。

    一个函数类型的变量是 FunctionN<> 接口的一个实现。其中 N 表示函数需要的参数个数,泛型依次为参数类型及返回值类型。

    FunctionN 中有一个 invoke 方法,该方法中可以写入 lambda 的主体。

    如下,调用函数类型为 (Int)->Unit 的 test 函数时,需要传入一个 Function1 的实例。因为表达式需要返回一个 Unit 类型的实例,该类型的实例只有 Unit.INSTANCE 一个,因此在 Java 中调用时需要显式返回:

            DemoKt.test(new Function1<Integer, Unit>() {
                @Override
                public Unit invoke(Integer integer) {
    
                    return Unit.INSTANCE;
                }
            });
    

    相关文章

      网友评论

          本文标题:函数类型

          本文链接:https://www.haomeiwen.com/subject/guupmftx.html