美文网首页
kotlin(二):基本语法之函数

kotlin(二):基本语法之函数

作者: 小川君 | 来源:发表于2018-09-03 00:06 被阅读0次
kotlin 中函数用fun来声明
fun onCreate(){
    
}

如果函数是继承的父类的话 需要用的override关键字override fun onCreate(){ } (反正重写的时候会自动加上,这里也不必过多的记忆区分,如果函数可以被继承则需要 open override fun onCreate(){ })

如果函数是有入参的话 fun onCreate(str: String) { }

kotlin的函数返回值在 ()之后以: 返回值类型的形式声明

无返回值情况下:
Unit是个空类型,类似于void,不过在kotlin中,如果函
数没有返回值,则可以不用声明 这一点跟java不同,当然也可以声明为Unit

fun person(){
    
}

fun person(): Unit{
    
}
这两个方法是相同的

有返回值的情况下: 直接return返回即可

fun person(): String{
    return "str"
}
函数的命名
  fun person(name: String,age: Int = 0,job: String = "xxx",isMan: Boolean = false): Unit{
        println("name:$name  age: $age  job:$job isMan:$isMan")
    }

我们声明一个描述person的函数,其中age,job和isMan都有默认值
正常情况下我们调用方式是(函数所在的类是KtolinTest):

mKtolinTest.person("chuan",1,"android",true)

因为我们在声明函数的时候 部分参数有了默认值,如果我们要使用默认值得话再调用函数的时候可以不用再次传值

mKotlinTest.person("chuan")

输出为I/System.out: name:chuan age: 0 job:xxx isMan:false

其次我们在调用函数的时候 可以通过属性名:属性值的方式来作为函数的入参,提高可读性,而且使用这种方式的话,可以不用依赖函数的入参顺序

kotlinTest.person(name = "chuan",isMan = true,job = "android")

输出为 name:chuan age: 0 job:android isMan:true

注意:使用命名参数时,所有位置参数都要放在命名参数之前,例如:

kotlinTest.person("chuan",isMan = true)

kotlinTest.person(isMan = true,"chuan")这样是不可以的,即:命名参数位于最后位置

局部函数

平常我们用到的函数都是成员函数,成员一词也是与成员变量相对的,反正本人没有接触过,不过局部变量倒是接触比较多 /手动滑稽,在ktolin中就有了相应的局部函数
,即函数内部的函数

  fun person(name: String,age: Int = 0,job: String = "xxx",isMan: Boolean = false){
        var mName: String = name
        fun job(a: Int): String{
            return "name:$name  a:$a"
        }
        var str: String = job(age)
        println("name:$name  age: $age  job:$job isMan:$isMan")
    }

按照官方的来说就是声明一个局部作用域,仅供父函数调用,如果其他的成员函数也可以调用的话,则可以声明一个成员函数,局部函数中可以调用父函数的局部变量
以往我们可能在写一个功能的时候,会使一个函数的代码量变的很大,然后我们会抽出部分函数作为成员函数,供当前函数调用,抽出来的函数如果有其他的成员函数引用还好,如果只是仅有一个函数调用的话 可读性会降低很多,如果一个函数调用另一个函数再调用另一个函数的话,这种深层次的调用,会使人很抓狂,因为当前函数看完了,上一个函数的作用可能忘记了,也有可能参数的意义忘记了等等,局部函数还是值得一试的

可变数量的参数

在java中如果是可变数量的参数,直接..即可,但是在kotlin中 则需要使用vararg关键字来声明

fun foo(vararg ts: String,str: String){
    
}

这算是一个比较特殊的vararg函数,因为你不知道到哪里是ts,到哪里是str
此时我们可以这样使用

kotlinTest.foo("chuan","chuan","chuan","chuan","chuan",str = "chuan")

来避免一些冲突问题

中缀表示法

表示在调用用infix关键字修饰的函数时,可以忽略调用的点和圆括号

   infix fun foo(type: String): Int{
        var re: Result = function()
        var (resu,sta) = re
        println("result:$resu  status:$sta")
        return 1
    }
    
    fun Main(){
        this foo "chuan"
    }

抛开函数里面的逻辑不看,但看调用,普通调用是this.foo("chuan"),如果使用中缀表示法调用的话则是this foo "chuan"
中缀函数需要满足的要求:
他们必须是成员函数或者扩展函数
他们必须只有一个参数
其参数不得接收可变数量的参数且不能有默认值

foo函数内部包含有解构声明 这一部分在kotlin(三)中会提到

data class Result(){}
扩展函数

上面说到了扩展函数,这里就说一下

声明一个扩展函数,我们需要用一个被扩展的类型来作为他的前缀,以KotlinTest类为例

// 声明一个测试类
class KotlinTest{
    fun test(){
        
    }
}
// 声明一个调用类
class Mult{
    fun Main(){
        KotlinTest kotlinTtest = KotlinTest()
        // 调用KotlinTest类的扩展方法 
        kotlinTest.Main()
    }
    // 为KotlinTest类声明一个扩展方法 
    fun KotlinTest.Main(){
        println("KotlinTest Main ")
    }
}

如上所示,最后输出的是/com.chuan.jun I/System.out: KotlinTest Main
注意:KotlinTest.Main()的调用只能在声明类里面调用,如果此时还有一个类Test,即使我们有kotlinTest对象,但也调用不到Main函数

如果我们在KotlinTest类中 声明一个Main函数,那么在Mult中调用Main函数的时候,会调用KotlinTest的Main函数,不会调用扩展函数Main

class KotlinTest{
    fun test(){
        
    }
    fun Main(){
        println("-------KotlinTest Main-------")
    }
}

class Mult{
    fun Main(){
        KotlinTest kotlinTtest = KotlinTest()
        // 调用KotlinTest类的扩展方法 
        kotlinTest.Main()
    }
    // 为KotlinTest类声明一个扩展方法 
    fun KotlinTest.Main(){
        println("KotlinTest Main ")
    }
}

输出为com.chuan.jun I/System.out: -------KotlinTest Main-------

扩展还有一种省略函数名的,不知道这种的是什么意思,有什么注意点,可能跟扩展属性有关,有知道的同学留言下,写法如下

var kk = fun KotlinTest.(age: Int): KotlinTest = this.also {  println("kkkk---$age") }

声明一个函数表达式fun KotlinTest(age: Int): KotlinTest = this.also { Main() } 其中this表示KotlinTest本身,也就是fun后面的那个KotlinTesty,
this.also返回KotlinTest类型的对象,后面会单独说,并且调用了KotlinTest的Main方法,我们来调用下

kotlinTest: KotlinTest = KotlinTest()
kotlinTest.kk(1)

输出为:com.chuan.jun I/System.out: kkkk---1
内联扩展函数
  • let:let扩展函数的实际上是一个作用域函数,当你需要去定义一个变量在一个特定的作用域范围内,let函数的是一个不错的选择;let函数另一个作用就是可以避免写一些判断null的操作。
object.let{
it.todo()//在函数体内使用it替代object对象去访问其公有的属性和方法
...
}

//另一种用途 判断object为null的操作
object?.let{//表示object不为null的条件下,才会去执行let函数体
it.todo()
}
实例:
var kar: String = kotlinTest.let {    // 定义变量kar,变量类型为String
            it.person(name = "chuan")  // it代表kotlinTest对象 调用kotlinTest的person对象
            "chuan2222"   // 最后一行为返回值
println(kar)
输出chuan2222
  • with
with(object){
   //todo
 }
 
 实例:
var kar: String = with(kotlinTest){
    Main()
    "chuan"
}

总的来说跟let的使用差不多
  • run
object.run{
//todo
}
run函数实际上可以说是let和with两个函数的结合体,run函数只接收一个lambda函数为参数,以闭包形式返回,返回值为最后一行的值或者指定的return的表达式。
  • apply
object.apply{
//todo
}

实例:
var  kar = kotlinTest.apply { it.Main() }
kar.Main()
        
从结构上来看apply函数和run函数很像,唯一不同点就是它们各自返回的值不一样,run函数是以闭包形式返回最后一行代码的值,而apply函数的返回的是传入对象的本身。
  • also
object.also{
//todo
}

also函数和let很像,只是唯一的不同点就是let函数最后的返回值是最后一行的返回值而also函数的返回值是返回当前的这个对象。

相关文章

网友评论

      本文标题:kotlin(二):基本语法之函数

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