美文网首页
Kotlin-----方法进阶

Kotlin-----方法进阶

作者: 会写代码的小猿猴 | 来源:发表于2022-01-08 17:25 被阅读0次

    在kotlin中我们将函数作为参数或者返回值的函数叫做高阶函数,也就是使用方法体作为参数的方法叫做高阶方法。

    • 函数作为参数

    我们通过一个实战来了解它的定义
    实战:需求-----实现一个可以对集合元素进行求和的高阶函数,并且每遍历一个元素都要有回调。

    fun List<Int>.sum(callback:(Int) ->Unit):Int{
        var result=0
        for (v in this){
            result+=v
            callback(v)
        }
        return result
    }
    

    这个方法用到了扩展,直接使用List的扩展创建方法,在方法内部使用this关键字访问该集合,关于扩展可能有很多兄弟不清楚,所以我列出了它不用扩展的方法,如下:

    fun test6(list: List<Int>,callback: (Int) -> Unit):Int{
        var result=0
        for (v in list){
            result+=v
            callback(v)
        }
        return result
    }
    

    方法中的第二个参数是一个回调,callback: (Int) -> Unit这句代码表示返回一个int型数据,Unit表示默认返回为空。再来看一下它的调用。

    val list = listOf(1, 2, 3, 4)
      val sum = test6(list,{
            println(it)
        } )
        println(sum)
    

    这里我分别打印了这个集合的每一项和所有元素的和,我们可以看到在第二个参数的地方我们实现了callback函数,所以test6方法的第二个参数是callback方法,callback方法等同于

    fun callback(it:Int){
            println(it)
        }
    

    这就是将函数作为参数的高阶函数。

    • 函数作为返回值

    同样的先来做一个小实战
    需求-----实现一个高阶函数,并且返回一个声明为(scale:Int)->Float的函数,返回的函数可以求取集合元素所有和的scale倍。
    注:scale:Int)->Float的意思可以用lambda来理解:该函数接收一个scale的Int型参数,返回一个Float的参数。

    fun test7(list: List<Int>): (scale: Int) -> Float {
        println("这是方法的第一层")
        return fun(scale): Float {
            var result = 0F
            for (v in list) {
                result += v * scale
            }
            return result
        }
    }
    

    调用:

      val list = listOf(1, 2, 3, 4)
        val result=test7(list)(2)
        println(result)
    

    注意调用的格式就好了,第二个(2)是表示向返回的函数传递的参数,其实可以理解为它是一个两层函数,调用时第一个括号(list)表示向test7方法传递list参数,第二个括号(2)表示向test7的返回函数传递参数2.

    • 方法中的闭包(closure)

    闭包可以理解为能够读取其他方法内部变量的方法,所以说闭包是将方法内部与方法外部连接起来的桥梁。
    闭包的特性

    • 方法可以作为另一个方法的返回值或参数,还可以作为一个变量的值。
    • 方法可以嵌套定义,即在一个方法内部可以定义另一个方法。
      闭包的好处:
    • 加强模块化
    • 抽象
    • 灵活
    • 简化代码
      说再多也没用,来个实战。
      实战:
      ◆需求:实现一个testClosure方法 ,该方法要接收一个Int类型的v1参数,同时能够返回一个声明为(v2: Int, (Int)-> Unit)的函数,并且这个函数能够计算v1与v2的和。
    fun testClosure(v1:Int):(v2:Int,(Int)->Unit)->Unit{
        return fun (v2:Int,printer:(Int)->Unit){
            printer(v1+v2)
        }
    }
    

    调用

    testClosure(2)(3){
            println(it)
        }
    

    这个例子有点复杂,要用心去理解一下,这个testClosure()接收一个参数v1,它的返回值类型是一个函数,我们暂时把它叫做f1,f1的构造是v2:Int,(Int)->Unit)这样的,表示f1接收两个参数,第一个参数是一个int型数据v2,第二个参数暂时叫做f2,f1没有返回值,f2是返回一个int型数据,后面加Unit让它暂时返回为空,最后一个Unit是表示整个testClosure()方法暂时返回为空。
    调用时第一个参数2是传递给方法testClosure()的参数v1,第二哥参数3是传递给函数f1的参数v2,it表示f2返回的值。
    上面这个例子是函数作为参数和返回值的一个复杂嵌套使用,要配合lambda表达式来理解。

    • Kotlin数据类的解构

    这是一个解析数据的小技巧,刚好用到就在这里分享一下,用完你就知道kotlin有多好了。

    data class Result(var message:String,var code:Int)
    fun test0(){
        var result1=Result("成功",1)
        var (msg,code)=result1
        println("message:$msg  code:$code")
    }
    

    仅作为分享,不多解释,平时接收后台接口数据可以用这种方式反解拿到接口中的某项数据。

    • 方法的字面值

    将方法定义为变量,可以作为变量去调用;

    fun test11(){
        var temp: ((Int) -> Boolean)? =null
        temp={num ->(num>10)}
        println(temp(11))
    }
    

    仅作为学习记录,大家好好看前面的内容这里应该不难理解。

    • kotlin中的构造方法

    kotlin在构造方法方面也比Java要方便许多,我们先来看最基本的构造方法怎么写:

    class KotlinClass (name:String){
    }
    

    kotlin中类的构造方法可以直接在类的声明时创建参数,比如上面例子就是直接实现了类KotlinClass 的主构造方法,该构造方法接收一个String类型的参数name,那我们都知道类的构造方法可以有多个,怎么声明多个构造方法呢?
    可以在类的内部声明多个构造方法,上面例子的叫做主构造方法,类中声明的都叫次构造方法,次构造方法在声明时都要调用主构造方法。

    class KotlinClass (name:String){
        constructor(age:Int,name: String):this(name){
            println("name:$name")
        }
        constructor(age: Int,name: String,phone:Long):this(name){
            println("phone:$phone")
        }
    }
    

    如上所示,我们在类的内部定义了两个次构造方法,都通过this关键字调用了它的主构造方法。
    下面是对每个构造方法的调用:

     /*调用类的主构造方法*/
        var name="zzp"
        KotlinClass(name)
        /*调用类的第一个次构造方法*/
        KotlinClass(20,"zzp")
        /*调用类的第二个次构造方法*/
        KotlinClass(20,"zzp",110)
    

    kotlin的构造方法大致如上所示,接下来我说一点在开发中经常会用到的,上面的例子以主构造方法为例,我们可以在主构造方法传入一个name的字符串,假如我们需要在类里面的某个方法操作这个name,怎么拿到它呢?按照Java的办法也可以拿到,代码如下:

     var name1:String=""
        constructor(age: Int, name: String) : this(name) {
            name1=name
            println("name:$name")
        }
    

    我们需要再定义一个变量name1,在构造方法中将构造方法的参数name赋值给name1,这样才能拿到构造方法的参数,kotlin还有一个更简单的方法,在构造方法参数列表就对该参数进行声明。

    class KotlinClass(val name: String) {
        fun println(){
            println(name)
        }
    }
    

    在参数前面加了个val声明name,然后就可以直接在下面的方法体内直接调用name变量。这也算是一个小技巧了。当然不加var/val也是可以直接使用构造方法参数的,就要用到初始代码块init了

    init {
            println(name)
        }
    

    这样也是可以的,我们只需要把所有方法在init内部调用就可以了。

    • kotlin继承如何写子类构造方法

    这个非常简单,只需要记住一点,子类的构造方法必须先调用父类构造方法,这点和Java是一样的,还不清楚继承的可以先看我的另一篇文章Java-----继承

    open class Animal(val age: Int)
    class Dog(age: Int) :Animal(age)
    

    如上所示,kotlin继承使用冒号,在后面跟上父类构造方法就可以了。父类需要用open关键字修饰才能被继承,类似于Java的public。

    扩展:kotlin继承子类如何重写父类构造方法、如何覆盖父类成员变量
    open class Animal(val age: Int) {
        open var foot: Int = 0
        open fun printM(){
            println("动物有很多脚")
        }
    }
    
    class Dog(age: Int) : Animal(age) {
        //覆盖父类成员对象
        override var foot=4
        //重写父类成员方法
         override fun printM(){
            println("狗有四只脚")
         }
    }
    

    重写父类的成员方法或者覆盖它的成员变量都需要先使用open关键字将父类的成员变量和成员方法打开,在子类中重写时加上override修饰。

    相关文章

      网友评论

          本文标题:Kotlin-----方法进阶

          本文链接:https://www.haomeiwen.com/subject/gwmecrtx.html