This article has participated in the third “topic writing” track of the Denver Creators Training Camp. For details, check out: Digg Project | Creators Training Camp third is ongoing, “write” to make a personal impact.

A 🌻 higher-order function instead of a callback

1.1 No Parameter Example

fun main(a) {
    pay(Runnable {
        println("Callback function..")
    })
    pay{
        println("Higher order functions..")}}fun pay(block: Runnable) {
    println("before block")
    block.run()
    println("end block")}fun pay(block: () -> Unit) {
    println("before block")
    block()
    println("end block")}Copy the code

Output results:

End block Before block The higher-order function end blockCopy the code

It doesn’t make much difference. When the requirements change and I want to add a String to the callback method, how do I do that?

1.2 Examples with Parameters

// Define the interface
interface Consumer {
    fun accept(way: String)
}

fun main(a) {
    pay(Consumer {
        println("The callback function.. it=$it")
    })
    pay{
        println("Higher order functions.. it=$it")}}fun pay(block: Consumer) {
    println("before block")
    block.accept("Alipay")
    println("end block")}// String refers to the method parameter
fun pay(block: (String) - >Unit) {
    println("before block")
    block("Alipay")
    println("end block")}// Int is the return value of the block function
fun pay2(block: (String) - >Int) {
    println("before block")
    block("Alipay")
    println("end block")}Copy the code
  • If it is in the form of a callback, you need to create an interface and define parameters. If the parameters become two, you need to create another interface.
  • whileHigher order function of KTIt’s more flexible to use.

🌵 inline function

2.1 introduction

  • Definition: Prefix the method name with ainlineIt’s an inline function
  • Purpose: Reduce function calls to optimize performance
  • Usage scenario: Adding an inline to the front of each function does not optimize performance if a method’s parameters containHigher-order functionsThat suggests inline. A typical application scenario is Kotlin’s collection class.

filter 和 mapThe arguments in these methods are higher order functions, so these two methods plusinlineAfter keyword, these two methods are called to reduce nesting and optimize performance, as shown in the following example.

2.2 Non-inline functions

fun main(a) {
    pay(Runnable {
        println("Callback function..")
    })
    payNoInline{
        println("Higher order functions..")}}fun pay(block: Runnable) {
    println("before block")
    block.run()
    println("end block")}fun payNoInline(block: () -> Unit) {
    println("before block")
    block()
    println("end block")}Copy the code

The relevant Java code decomcompiled by bytecode is as follows:

  • Finding that higher-order functions as arguments are no different from method callbacks,
  • Additional classes have also been added to the method parametersFunction0andblock.invoke()Function call overhead.

2.3 🔥 Inline functions

fun main(a) {
   pay(Runnable {
       println("Callback function..")
   })
   payInline{
       println("Higher order functions..")}}...fun payInline(block: () -> Unit) {
   println("before block")
   block()
   println("end block")}Copy the code

The relevant Java code decomcompiled by bytecode is as follows:

  • When payInline is called, the method body inside payInline() is taken and executed as a whole with the current higher-order function.

  • The payInline () method is not called and block.invoke() is not called, much more efficient.

  • When a parameter in a function is a higher-order function, it is recommended that you modify the function inline.

Three 🌷 generics

3.1 🔥reified is highly recommended

  • Reified is a kt keyword unique to generics. It is used to make something abstract more concrete or real, making generics easier and safer to use.
inline fun <reified T : Activity> Activity.openAct(a) {
    startActivity(Intent(this, T::class.java))
}

fun <T : Activity> Activity.openAct(clazz: Class<T>) {
    startActivity(Intent(this, clazz))
}

fun main(a){
    // Start the Activity
    openAct(MyAct::class.java)
    
    // Start the Activity
     openAct<MyAct>()
}
Copy the code

When reified is used, it must be inline. Goodbye.class. Java and hello reified

3.2 Upper Bound Constraints (Out or extend)

  • Java: T extends Object
  • Kotlin:T : Object å’Œ out : Object

This means that the type must be a subtype or itself. Out generally returns a generic type as an object, as explained in out covariant below.

The class diagram looks like this:

open class People
open class Man : People(a)class Man1 : Man(a)class Man2 : Man(a)class User<T : Man>

fun <T> createUser(user4: User4<out Man>){}

fun main(a) 
    var u = User<Man>() // Generics can be themselves
    var u1 = User<Man1>()  // Generics can be subclasses
   // var u2 = User
      
       (
      
   
    val c1 = createUser(User4(Man1()))
   // val c2 = createUser(User4(People())
}
Copy the code

3.3 Lower Bound Constraints (in or super)

  • In Java is ? super Object
  • Kotlin isin Object
open class People open class Man : People() class Man1 : Man() class Man2 : Man() class User<T : Man> fun main() {var list: ArrayList<in Man> = ArrayList () list.add(Man()) List. Add ((Man) Man1); List.add (Man1())) // // Because manually add() data must be absolutely secure (the lowest parent: itself) to pass through. So you can't add the parent class directly. Fun getMan(): ArrayList<Man> = ArrayList() fun getMan1(): ArrayList<Man1> = ArrayList() fun getPeople(): ArrayList<People> = ArrayList() list = getMan() // list = getMan()Copy the code

3.4 Type Qualification (WHERE)

interface Fly
class Man
class Man1 : Man.Fly
class Man2 : Man
// Restrict the T passed in to Man or a subclass of it and implement the Fly interface
class User<T>(var t:T) where T: Man, T:Fly
fun main(a) {
    var u1 = User(Man1())
   // var u2 = User(Man2()
}
Copy the code

3.5 change

3.5.1 track ofOut

If your class returns generics as internal methods, you can use out:

interface Creation<out T> {
    fun create(): T
}
Copy the code

Create Creates the specified generic object. So create = output = out.

3.5.2 In (inverter)

If your class takes a generic object as an argument to a function, you can use in:

interface Consumer<in T> {
    fun consume(item: T)
}
Copy the code

Consume specifies the generic object. Consume = input = in

3.5.3 Invariant (the same)

If you use generics as both a function parameter and its output, you don’t use either in or out.

interface CreationConsumer<T> {
    fun create(a): T
    fun consume(item: T)
}
Copy the code

Five for six cycles

// index traversal
for ((index, item) in arrayListOf("a"."b"."c").withIndex()) {
    println("$index - $item")// 0-a 1-b 2-c
}
// Bag left bag right
for (i in 1.10.) {
    println(i) / / 12345678910
}
// do not do right
for (i in 1 until 10) {
    println(i) / / 123456789
}
// descending order - package left package right
for (i in 10 downTo 1) {
    println(i) / / 10987654321
}
// Skip - bag left bag right
for (i in 1.10. step 2) {
    println(i) / / 13579
}
// do not do right
repeat(10) {
    print(it) / / 0123456789
}
Copy the code