阅读 127

Kotlin学习(2)-函数

使用fun关键字定义函数

private fun doSomething(age:Int,flat:Boolean) : String{
    return ""
}
复制代码

函数参数:

  • 默认值参:如果不打算传入值参,可以预先给参数指定默认值
  • 具名函数参数:如果使用命名值参,就可以不用管值参的顺序
private fun doSomething(age: Int = 2, flag: Boolean): String {
    return "result"
}

fun fix(name: String, age: Int = 2) {
    println("")
}

//具名
doSomething(flag = true,age = 10)
复制代码

Unit函数

  • 不是所有函数都有返回值,kotlin没有返回值的函数就是Unit函数,也就是说他的返回类型就是unit
fun fix(name: String, age: Int = 2): Unit {
    println("")
}
复制代码

Nothing类型:TODO函数的任务就是抛出异常,就是永远别指望它运行成功,发挥Nothing类型

反引号中的函数名

  • kotlin可以使用空格和特殊字符对函数命名,不过函数名要用一对反引号括起来
  • 为了支持kotlin和java互操作,而kotlin和java各自却有不同的保留关键字,不能作为函数名,使用反引号括住函数名就能避免冲突

匿名函数

  • 定义时不取名字的函数,我们称之为匿名函数,匿名函数通常整体传递给其他函数,或者从其他函数返回
  • 匿名函数对kotlin来说很重要,有了它,我们能够根据需要定制特殊规则,轻松定制标准库里的内置函数
    //返回长度
    val totle = str.count()

    //通过匿名函数给标准函数指定规则
    //返回g的个数
    str.count({ letter ->
        letter == 'g'
    })
复制代码

函数类型与隐式返回

  • 匿名函数也有类型,可以当做变量赋值给函数类型变量,就像其他变量一样,匿名函数就可以在代码中传递了。函数的类型,由传入的参数和返回值决定
  • 和具名函数不一样,除了极少数情况,匿名函数不需要return关键字来返回数据,匿名函数会隐式或者自动返回函数体最后一行语句的结果
    //变量func 的类型是 一个匿名函数
    val func: () -> String
    func = {
        val today = "today"
        //自动返回最后一行
        "$today nice"
    }
复制代码

和具名函数一样,匿名函数可以不带参数,也可以带一个或多个任意类型的参数,需要带参数时参数的类型放在匿名函数的类型定义中,参数名放在函数定义中

    //Int是参数类型在类型定义中  age是参数名在函数体中
    val func2: (Int) -> String = { age ->
        val today = "today"
        //自动返回最后一行
        "$today nice $age"
    }
复制代码

it关键字

只有一个参数的匿名函数,可以使用it关键字来表示参数名。当你需要传入两个参数时,it关键字就不好使了

    //使用it当做参数名 结果跟上边的例子是一样的
    val func2: (Int) -> String = {
        val today = "today"
        //自动返回最后一行
        "$today nice $it"
    }
复制代码

类型推断

定义一个变量时,如果已把匿名函数作为变量赋值给它,就不需要显示指明变量类型了

    //无参数匿名函数
    val func: () -> String = {
        val today = "today"
        //自动返回最后一行
        "$today nice"
    }
    
    //使用类型推断后
    val func4 = {
        "result"
    }
    
    //两个参数的匿名函数
    val func2: (Int, String) -> String = { age, name ->
        val today = "today"
        //自动返回最后一行
        "$today nice "
    }
    
    //使用类型推断后
    val func3 = { age: Int, name: String ->
        "$age $name"
    }
复制代码

Lambda

  • 将匿名函数成为lambda,将它的定义称为lambda表达式,他返回的数据称为lambda结果

定义参数是函数的函数(即函数的参数是另外一个函数)

    //具名函数 第二个参数是一个函数
    fun funcM(name: String, getWords: (String, Int) -> String) {
        //从1到24中随机取一个
        val hour = (1..24).shuffled().last()
        //调用第二个参数(函数) 并传入name和hour
        println(getWords(name, hour))
    }

    //匿名函数
    val getWords = { name: String, hour: Int ->
        val year = 2021
        "$year $name $hour"
    }
复制代码

简略写法

  • 如果一个函数的lambda参数排在最后,或者是唯一的参数,那么括住的lambda值参的一堆圆括号就可以省略
fun main() {

    //匿名函数
    val getWords = { name: String, hour: Int ->
        val year = 2021
        "$year $name $hour"
    }
    funcN("", getWords)
    
    //简写之后 直接讲匿名函数放在后面
    funcN("a") { name: String, hour: Int ->
        val year = 2021
        "$year $name $hour"
    }
}

//具名函数 第二个参数是一个函数
fun funcN(name: String, getWords: (String, Int) -> String) {
    //从1到24中随机取一个
    val hour = (1..24).shuffled().last()
    //调用第二个参数(函数) 并传入name和hour
    println(getWords(name, hour))
}

复制代码
函数引用
  • 要把函数作为参数传给其他函数使用,除了lambda表达式,kotlin还提供了其他方式,传递函数引用,函数引用可以把一个具名函数转成一个值参,使用lambda表达式的地方,都可以使用函数引用。
//函数实现
private fun doSth(name: String, num: Int): String {

    return "$name 有 $num 个"
}

//第二个参数为函数 调用时可以使用函数引用
private fun doSomething(name: String, doSth: (String, Int) -> String) {
    println(doSth(name,12))
}

//调用,第二个参数使用函数引用
doSomething("people", ::doSth)
复制代码
函数类型作为返回类型
  • 函数类型也是有效的返回类型,也就是说可以定义一个能返回函数的函数
//返回类型为函数的函数
fun getFunResponse(): (Int, String) -> String {

    return { hour: Int, name: String ->
        "$hour $name"
    }
}

  //调用 返回一个函数
  val funResponse = getFunResponse()
  //再调用返回的函数
  val funResponse1: String = funResponse(10, "cat")
复制代码

闭包

  • kotlin中,匿名函数能修改并引用定义在自己的作用域之外的变量,匿名函数引用着定义自身的函数里的变量,kotlin中的lambda就是闭包
  • 能接收函数或者返回函数的函数又叫做高级函数,搞基函数广泛应用于函数式编程当中

lambda与匿名内部类

  • 为什么使用函数类型?函数类型可以让开发者少写模式化代码,写出更灵活的代码。java8支持面向对象编程和lambda表达式,但不支持将函数作为参数传递给另一个函数或者变量,java的替代方案是匿名内部类

java使用匿名内部类的实现

    public static void main(String[] args) {

        //使用实现类的方式
        show("cat", new MyDiscountWords());
        
        //通过匿名内部类调用
        show("dog", new DisCountWords() {
            @Override
            public String getWords(String name, int num) {
                return name + num;
            }
        });
    }

    public static void show(String name, DisCountWords disCountWords) {
        int num = new Random().nextInt(24);
        System.out.print(disCountWords.getWords(name, num));
    }

    //定义一个接口
    public interface DisCountWords {
        String getWords(String name, int num);
    }
    
    //定义实现类
    static class MyDiscountWords implements DisCountWords {
        @Override
        public String getWords(String name, int num) {
            return name + num;
        }
    }
复制代码

使用kotlin方式

//使用函数作为参数
fun show(name: String, getWords: (String, Int) -> String) {
    var num = (1..24).shuffled().last()
    print(getWords(name, num))
}
//调用show方法
show("cat") { name: String, num: Int ->
        "$name $num"
}
复制代码
文章分类
Android
文章标签