行为参数化/策略模式 && Lambda表达式
这篇文章不涉及Lambda表达式的具体使用,只谈谈我对其的一些理解。不一定对,如有偏颇,望指正。
行为参数化/策略模式
Java是一门面向对象的语言。
奉行一切皆对象,需要什么就把这个他当作对象传递进来。不过有一个东西Java不能直接将其作为对象——方法。
这里的方法
可不是Java反射中的Method
类。举个栗子~
有个方法需要传入两个Int
,一个计算的方法
,最后输出计算的值。我们也不知道这个方法
会有哪些可能的行为,所以也不能定义一个类与现实中的+-*/方法一一对应。
这时候我们就会想起设计模式中的策略模式。
定义一个接口,里面一个运算方法。
1 | class CalTest<T>{ |
需要使用的时候传入这个接口的具体实现即可。
1 | CalTest calTest = new CalTest(); |
通过这种模式,我们相当于将Calculation
中的onCalculate
方法传递了。
这是一个历史悠久的变通方案,很长一段时间我们都是这么写的。
虽然我们不能传递方法
,我们可以将方法
通过接口的方式“实例化”,将这个方法当作一个对象传到了另一个方法中去。这也就是所谓的行为参数化。
Java中的Lambda表达式
在Java1.8
中,新增加了Lambda表达式。主要是针对以上匿名类的方式“实例化”接口的时候,可以进行简写。
以上代码可改为:
1 | calTest.calculate(1, 2, (a, b) -> a+b); |
实际上Lambda表达式就是对通过接口实现的匿名类的一种简写。没有任何特别的新功能,Lambda能实现功能不用Lambda也能实现,不用Lambda实现不了的功能用Lambda也实现不了。
于是乎,你也可以将这整个Lambda表达式视作一个行为
,它同样可以作为参数进行传递。
Kotlin中的Lambda表达式
Kotlin
中的Lambda和Java又不太一样。或者说看上去一样,实际是不一样的。
Kotlin
中是有一个专门的写法来表示“方法或行为”这种对象的。
比如以上的例子中,我们需要传入一个“输入两个Int,返回一个泛型类T的方法/行为”这样一个行为对象。
在Kotlin
中就是用(a:Int,b:Int) -> T
来表示。所以以上代码用Kotlin
的写法为:
1 | fun<T> calculate(a: Int,b: Int,cal:(a:Int,b:Int) -> T){ |
使用起来这样写:
1 | calculate(1,2,fun(a,b){ |
当然,用Lambda表达式的形式来写,就是这样。
1 | calculate(1,2,{a: Int, b: Int -> |
Lambda自带有类型推断功能,所以传入的Int也可以不要。
另外,如果这个Lambda是Kotlin
函数中的最后一个对象,Lambda表达式还可以再简化一点,写到括号外面:
1 | calculate(1,2) { a, b -> |
如果这个Lambda是Kotlin
函数中唯一的一个对象,括号也可以去了;
如果这个Lambda是单参数的,参数也可以不加,默认为it。
例如Android中的:
1 | view.setOnClickListener{ |
所以,Kotlin
中的Lambda 和 Java8
中的Lambda 是不一样的:Java8
中的Lambda
只是一种便捷写法,而kotlin
中的Lambda是实实在在的对象!
参考: