简书人物Kotlin专题程序员

39. 复合函数

2017-11-29  本文已影响34人  厚土火焱

复合函数有什么用呢?可以简单解释为,一个函数的参数是另一个函数,直接用另一个函数完成这个复合的功能。
还是看个例子吧。先写两个函数

val add5 = {i:Int -> i + 5}
val multiplyBy2 = {i:Int -> i * 2}

一个实现了加法,一个实现了乘法。调用如下

    println(multiplyBy2(5))
    println(add5(3))

我们也可以这样

println(multiplyBy2(add5(3)))

把 add5 之后的结果,再进行 multiplyBy2 运算。
只是这样写,如果调用的地方多了似乎比较麻烦啊!这时候就可以写一个复合函数了。

infix fun <P1,P2, R> Function1<P1,P2>.andThen(function:Function1<P2, R>):Function1<P1, R>{
    return fun (p1:P1):R{
        return function.invoke(this.invoke(p1))
    }
}

infix 是中缀修饰符,方便调用的。
fun <P1,P2, R> 中P1,P2是参数,R是返回值。
Function1<P1,P2>中 P1是参数,P2是返回值。这里的Function1表示传入的参数是个Function。
andThen是Function1的扩展。
参数就是 Function1函数。
返回值也是Function1函数。
这个函数的调用是这样的

    val add5AndMultiplyBy2 = add5 andThen multiplyBy2
    println(add5AndMultiplyBy2(3))

调用的关键,就是那个扩展函数名。
这个名字(andThen)按照我们的喜好来定义就可以。
先运行一下看结果。

10
8
16
16

再写一个同样通能的,换个名字看看。

infix fun <P1,P2, R> Function1<P1, P2>.jiXuZuo(function: Function1<P2, R>):Function1<P1, R>{
    return fun(p1:P1):R{
        return function.invoke(this.invoke(p1))
    }
}

然后这样调用

    val addJiXuZuoMultiplyBy2 = add5 jiXuZuo multiplyBy2
    println(addJiXuZuoMultiplyBy2(3))

运行结果也是 16
只是,这种调用有点不走寻常路,是吗?这就是 infix 的妙用。如果你去掉它,就要像一般的函数那样调用了。
我们再写一个一样功能的函数,但是不加 infix

    val addJiXuZuoMultiplyBy2 = add5 jiXuZuo multiplyBy2
    println(addJiXuZuoMultiplyBy2(3))

它的调用就不同了,要这样写

    val addFuheMultiplyBy2 = add5.fuhe(multiplyBy2)
    println(addFuheMultiplyBy2(3))

这样是不是就很熟悉了?
也不仅仅是 Int,其他类型也是可以这样写复合函数的。下面用 String 再调用一下。

val myname = { str: String -> "my age is " + str }
val age = { i: String -> i }

在 main 里这样写

    println(age(myname("six")))
    val mynameAndAge = age jiXuZuo myname
    println(mynameAndAge("seven"))

运行的结果是

my age is six
my age is seven

在处理P1,P2的时候,千万别弄错顺序哦。不然结果就完全不同了。当然,String 类型好像没这种烦恼。

上一篇 下一篇

猜你喜欢

热点阅读