Lambda表达式

Kotlin高阶函数--Higher-Order Function

参数或者返回值为函数类型的函数,在Kotlin中被称为高阶函数。

高阶函数概念源自数学中的高阶函数-在数学中,如果一个函数使用函数作为他的参数或者结果,则他被称为高阶函数。

Java中函数的参数不能是函数

Kotlin中函数可以含有函数类型的参数,且函数的返回值也可以是函数类型

SAM接口--Single Abstract Method

只有一个抽象方法的接口简称SAM接口

函数类型的参数示例

  • 无参数无返回值:(()->Unit)

  • 单Int型参数返回:String(Int->String)

双冒号::method是什么?(函数引用Function Reference)

::method这种写法叫做函数引用;(method在加上::就变成了一个和函数具有相同功能的对象了)

  • 对于一个已经声明好的函数,不管是要把它作为参数传递给函数,还是把它赋值给变量,都需要在函数名的左边加上双冒号

    a(::b)
    val d = ::b
    
  • 在Kotlin中,一个函数名的左边加上双冒号,它就不表示这个函数本身了,而是表示一个对象,或者是一个指向对象的引用,但是这个对象并不是函数本身,而是和函数具有相同功能的对象

    b(1) // 调用函数
    d(1) // 用对象 a 后面加上括号来实现 b() 的等价操作
    (::b)(1) // 用对象 :b 后面加上括号来实现 b() 的等价操作
    
  • 函数类型的对象和普通对象的区别:

    普通类型的对象无法通过对象()这种方法来调用,但是函数类型的对象是可以的,但是这其实是个假的调用,它是Kotlin的语法糖。

    对一个函数类型的对象加括号,加参数,真正调用的是这个对象的invoke()函数

    d(1) // 实际上会调用 d.invoke(1)
    (::b)(1) // 实际上会调用 (::b).invoke(1)
    
    //错误写法,对一个函数调用invoke
    b.invoke(1)
    
  • 双冒号加函数名是一个指向对象的引用,但是并不是指向函数本身。而是指向一个看不见的对象,这个对象复制了原函数的功能,但它并不是原函数

Kotlin中的匿名函数(其实是一个对象,并不是一个函数)

简单来说就是没有名字的函数,本质是一个对象

a(fun(param: Int): String {
    return param.toString()
});
val d = fun(param: Int): String {
    return param.toString()
}
//错误写法,左右两边都有名字,Kotlin是不允许的
val d = fun a(param:Int):String{
    
}

Java中和Kotlin中接口回调设计及使用对比

  • Java

    //定义
    public interface OnClickListener {
      void onClick(View v);
    }
    public void setOnClickListener(OnClickListener listener) {
      this.listener = listener;
    }
    //使用
    view.setOnClickListener(new OnClickListener() {
      @Override
      void onClick(View v) {
        switchToNextPage();
      }
    });
    
  • Kotlin

    //定义
    public interface OnClickListener {
      void onClick(View v);
    }
    fun setOnClickListener(onClick: (View) -> Unit) {
      this.onClick = onClick
    }
    //使用
    view.setOnClickListener(fun(v: View): Unit) {
      switchToNextPage()
    })
    //使用lambda替换
    view.setOnClickListener({ v: View ->
      switchToNextPage()
    })
    

Lambda表达式

  • Lambda表达式示例:

    (parameters) -> expression
    或
    (parameters) ->{ statements; }
    
    // 1. 不需要参数,返回值为 5  
    () -> 5  
    
    // 2. 接收一个参数(数字类型),返回其2倍的值  
    x -> 2 * x  
    
    // 3. 接受2个参数(数字),并返回他们的差值  
    (x, y) -> x – y  
    
    // 4. 接收2个int型整数,返回他们的和  
    (int x, int y) -> x + y  
    
    // 5. 接受一个 string 对象,并在控制台打印,不返回任何值(看起来像是返回void)  
    (String s) -> System.out.print(s)
    
  • 当Lambda是函数的最后一个参数,或唯一参数,或单参数时的不同写法

    //Lambda是函数的最后一个参数,可以把Lambda写在括号外面
    view.setOnClickListener() { v: View ->
      switchToNextPage()
    }
    //Lambda是函数的唯一参数,直接将()去掉
    view.setOnClickListener { v: View ->
      switchToNextPage()
    }
    //如果Lambda中函数时单参数的,参数也可以省略不写
    view.setOnClickListener {
      switchToNextPage()
    }
    //如果Lambda中函数时多个参数,但是部分参数不需要使用时
    mAdapter.setOnItemClickListener { _, _, position ->
      SocietyHomeAct.toSocietyHome(this, (mAdapter.getItem(position)))
    }
    
  • Kotlin对于省略的唯一参数有默认名字:it

  • Lamda的返回值不是用return返回,而是直接取最后一行代码的值

  • 将匿名函数赋值给变量而不是作为函数参数传递的时候的写法

    val b = fun(param: Int): String {
      return param.toString()
    }
    //简写成Lambda
    val b = { param: Int ->
      return param.toString()
    }
    //错误写法
    val b = {
      return it.toString() // it 报错,因为无法根据上下文推断对象
    }
    //替代方案:给左边的变量指明类型
    val b: (Int) -> String = {
      //错误写法:Lambda的返回值不能用return返回,会直接取最后一行作为返回值
      //return it.toString() // it 可以被推断出是 Int 类型
      it.toString() // it 可以被推断出是 Int 类型
    }
    

Kotlin里的函数和匿名函数以及Lambda表达式的本质

它们都是函数类型的对象

  • 函数:用来实现特定功能的代码块

  • 匿名函数:不是一个函数,是一个具备与函数功能相同的对象

  • Lambda:不是一个函数,是一个函数类型的对象

  • 使用时能怎么使用双冒号加函数名就能怎么使用匿名函数,以及怎么使用Lambda表达式。

Kotlin中的Lambda和Java8的Lambda区别

Java从8开始引入了Lambda支持,主要作用是对于单抽象方法的接口,Java 8允许你用Lambda表达式来创建匿名类对象,但是它本质上还是创建了一个匿名类对象,只不过是一种简化的写法。

Kotlin中的Lambda是实实在在的函数类型的对象,功能更强,写法更多更灵活,

  • Kotlin中的Lambda是函数类型的对象
  • Java 8中的Lambda只是一种便捷的写法,在功能上没有突破

总结

  • 1、在Kotlin中,有一类Java不存在的类型,叫函数类型,这类对象可以当函数来使用的同时,还可以作为函数的参数,函数的返回值,以及赋值给变量

  • 2、创建一个函数类型的对象的三种方式

    ::b//双冒号加函数名
    val b = fun(){}//匿名函数
    val c = {}//Lambda
    
  • 3、双冒号加函数名、匿名函数和Lambda本质都是函数类型的对象;在Kotlin中,匿名函数不是函数,Lambda也只是代码块,Kotlin的Lambda可以归为函数类型的对象。

你可能感兴趣的:(Lambda表达式)