Kotlin introduced the concept of higher-order functions to improve coding efficiency in some scenarios

What are higher-order functions

Colloquially speaking, it is similar to the concept of higher-order functions in mathematics, that is, the parameters of functions can be functions. Of course, the return value can also be a function.

2. Analysis of kotlin high-order functions

1. View onClickListener (kotlin

 tV.setOnClickListener {
            //doSomeThing
        }
Copy the code

The lamba expression inside is a function

Not very graphic? Now look at filter and map in the set

listOf(1, 2, 3)
            .filter { it > 2 }
            .map { it + 5 }

/**
 * Returns a list containing only elements matching the given [predicate].
 */
public inline fun <T> Iterable<T>.filter(predicate: (T) -> Boolean): List<T> {
    return filterTo(ArrayList<T>(), predicate)
}
Copy the code

The argument to filter and map is a lambda function

2. What is the use of higher-order functions

In the case of the filter function, for example, to implement a filter logic, it’s ok to say that if classA and classB both need to call this function, then the function needs to be compatible with both cases

fun filter(): Boolean {
        if (classA) {
            return true
        } else if (classB) {
            return false
        }
        return false
    }
Copy the code

If else is fine, but if classC classD… We have to think about it. It clearly violates the open close principle. It is natural to be abstract rather than concrete, of course, abstract classes or interfaces.

If you implemented it the Java way, it would look like this

interface IJudge {
        fun canFilter(): Boolean
    }

    class ClassA : IJudge {
        override fun canFilter(): Boolean {
            return true
        }
    }

    class ClassB : IJudge {
        override fun canFilter(): Boolean {
            return false}} Fun filter(a:Int,b:Int,jugde: IJudge): Boolean {// add some logicreturn jugde.canFilter()
    }
Copy the code

This is a tough one, so you have to add this interface for abstraction, and then write more code.

If you use higher order functions

Fun filter(a: Int,b:Int, canFilter: (a:Int,b:Int) -> Boolean): Boolean {// Add some logicreturnCanFilter (a,b)} // call 1 filter(1, 2) {a: Int, b: Int -> a * b > 10} Int -> a + b < 5 }Copy the code

This saves an interface, which is actually generated by the compiler

Third, the implementation of Kotlin higher-order functions

Let’s see how the Kotlin compiler works by decomcompiling that kotlin code into Java, okay

Kt: fun filter(a: Int,b:Int, canFilter: (a:Int,b:Int) -> Boolean): Boolean {// Add some logicreturn canFilter(a,b)
    }
java:
 public final boolean filter(int a, int b, @NotNull Function2 canFilter) {
      Intrinsics.checkParameterIsNotNull(canFilter, "canFilter");
      canFilter.invoke(a, b);
      return (Boolean)canFilter.invoke(a, b);
   }
Copy the code

Actually Functions built into KT. Kt

So from here we can get the above conclusion:

A) function can omit an interface that has only one method

Canfilter.invoke (a,b); canfilter.invoke (a,b); This is useful when a function needs to be nulled. For example, replacing interface callbacks with only one method can be callback? .invoke(a,b,c), because callbck? (a,b,c) will not compile.

C. Although the functions.kt file has a finite number of methods, it feels like lambda parameters are finite, up to 22 parameters, beyond which compilation will fail. But when it does, another functionn.kt is called

operator fun invoke(vararg args: Any?) : RCopy the code

But if who writes the function, directly pass more than 20 parameters are not sealed into an object or builder, even the legs have to be interrupted…….

Fourth, the discussion about higher-order function replacement interface

As discussed above, when an interface has only one method, you can indeed omit an interface by using higher-order functions instead.

But when an interface has more than one method, you obviously can’t replace it directly. It’s possible to wrap several functions together, but it still feels redundant.

In parallel development, one person writes the UI and one handles the business logic using the UI. First set the interface, interface method documentation is written, at a glance. In this respect, interfaces are much better, and higher-order functions are more convenient when there is only one simple method.