Kotlin学习笔记

kotlin 学习

kotlin 中使用 vararg 标记可变参数,调用方法:

// 定义
fun test(vararg books : String){...}

// 使用
test("疯狂iOS讲义", "疯狂Android讲义")
var arr = arrayOf("疯狂Kotlin讲义", "疯狂Java讲义")
// 将数组的多个元素传给个数可变的参数
test(*arr)

特性:直接使用函数类型

kotlin 中可直接使用函数类型作为参数和返回值,如

fun map(data : Array,  fn: (Int) -> Int) : Array{...}

其中 fn: (Int) -> Int 就是使用函数类型,代表需要传入一个参数为 Int并且返回值为 Int 的函数。使用示例

// 设定一个方法
fun testfun(predicate: String):Boolean{
    return predicate.length > 3;
}

// fn传入参数为String,返回值为 Boolean 的方法 
fun useFun(a:String, fn:(String)->Boolean):String{
    val b:Boolean = fn(a)
    if (b) {return "big"} else {return "small"}
}

// 使用
var result:String = useFun("ja", ::testfun);

同理如使用函数作为返回值:

fun getMathFunc(type: String): (Int) -> Int {...}

关于 it 关键字

it:单个参数的隐式名称
一个 lambda 表达式只有一个参数是很常见的。

如果编译器自己可以识别出签名,也可以不用声明唯一的参数并忽略 ->。 该参数会隐式声明为 it:

ints.filter { it > 0 } // 这个字面值是“(it: Int) -> Boolean”类型的

调用示例:

// 省略形参名,用it代表形参
var square:(Int) -> Int = {it * it}
// 使用square调用Lambda
println(square(5))  // 输出25
println(square(6))  // 输出36

关于 lambda 表达式缩写

  • 传统写法,直接传入匿名函数

     var list = listOf("Java", "Kotlin", "Go")
     // 调用 List 的 dropWhile 方法需要传入 String->Boolean 类型的函数
     // 传统写法,直接传入匿名函数
     list.dropWhile(fun (predicate: String):Boolean{
         return predicate.length > 3;
     })
    
  • 第二种写法,提取匿名函数为一个方法

     fun testfun(predicate: String):Boolean{
         // 假设条件为大于3个字符的字符串
         return predicate.length > 3;
     }
     // 需要传入一个函数参数,与传统写法无区别
     var rt= list.dropWhile(::testfun)
    
  • 第三种缩写,将方法定义为一个lambda表达式传参

    var myfun = {predicate: String ->predicate.length > 3}
    var rt = list.dropWhile(myfun) 
    
  • 第四种缩写,将Lambda表达式放在括号后面,无需使用命名参数,省略形参名,用it代表形参

    var rt = list.dropWhile() {it.length > 3}
    
  • 第五种缩写,省略了 () ,最后一个参数是Lambda表达式,可将表达式写在括号外面

    var rt = list.dropWhile{it.length > 3}
    

lambda 调用

定义Lambda表达式,并在它后面增加圆括号可调用该Lambda表达式

var result = {base: Int , exponent:Int ->
    var result = 1
    for (i in 1 .. exponent) {
        result *= base
    }
    result
}(4, 3)

forEach 中的 lambda

 var list = listOf(3, 5, 30, -25, 14)
// 使用匿名函数执行forEach()方法
list.forEach(fun(n) {
    println("元素依次为:${n}")
    // 匿名函数中的return用于返回该函数本身,会打印出全部原始
    return
})

// 使用Lambda表达式执行forEach()方法
list.forEach{n->
    println("元素依次为:${n}")
    // Lambda表达式中的return用于返回它所在的函数(main函数),只打印第一个元素
    return
}

// 使用Lambda表达式执行forEach()方法
list.forEach(){n ->
    println("元素依次为:${n}")
    // 使用限定返回,此时return只是返回传给forEach方法的Lambda表达式,什么都不打印
    return@forEach
}

在类中自定义 getter 和setter 方法

kotlin 的getter 和setter 方法不走寻常路,需要注意

class Person(name: String, age: Int){
    // 使用private修饰属性,将这些属性隐藏起来
    var name = name
        set(newName){
            // 执行合理性校验,要求用户名必须在2~6位之间
            if (newName.length > 6 || newName.length < 2){
                println("您设置的人名不符合要求")
            } else {
                field = newName
            }
        }
        get() {
            println("执行 name 的getter方法")
            return "Alexander ken"
        }

    // 定义private修饰的属性,该属性是幕后使用
    private var _age: Int = age
    var age
    // 重写getter方法,返回幕后属性的值
        get() = _age
        set(newAge){
            // 执行合理性校验,要求用户名必须在2~6位之间
            if (newAge > 100 || newAge < 0){
                println("您设置的年龄不合法")
            } else {
                // 对幕后属性赋值
                _age = newAge
            }
        }


    var fullName
    // 使用单表达式定义getter方法的方法体
        get() = "${name}"
        set(value) {
            println("执行fullName的setter方法")
            // 如果value字符串中不包含.或包含几个.都不行
            if ("." !in value || value.indexOf(".") != value.lastIndexOf(".")) {
                println("您输入的fullName不合法")
            } else {
                var tokens = value.split(".")
            }
        }
}

fun main(args: Array) {
    var p = Person("李刚", 29)
    p.age = 120 // 赋值非法,不能赋值失败
    println(p.age) // 删除29
    p.age = 25 // 赋值合法,赋值成功
    println(p.age) // 输出25
    println(p.name)
    println(p.fullName)
}

实现接口

kotlin 与 java 的接口实现方式不同,在java 中我们可以直接 new 一个接口对象出来,但是 kotlin 需要使用 object 关键字,如实现 ActivityLifecycleCallbacks 接口:

        val activityLifecycleCallbacks = object : Application.ActivityLifecycleCallbacks {
            override fun onActivityCreated(activity: Activity?, savedInstanceState: Bundle?) {
                TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
            }
      
            ......    
            override fun onActivityDestroyed(activity: Activity) {
            }
        } 

另外需要注意将 :

  TODO("not implemented") 

这句 TODO 删除,否则会抛出异常:kotlin.NotImplementedError: An operation is not implemented: not implemented

“TODO("not implemented")” 这句代码,这句代码在运行的时候会抛出以上异常,这样做的好处是促使我们去实现接口方法或者手动删掉这句代码。

关于 kotlin 中的 ? 与 !! 以及 ?: 三个运算符的解释

这篇博客解释得不错,就不解释了

Kotlin中?和!!的区别
https://www.jianshu.com/p/51b2e5aa3dd8

你可能感兴趣的:(Kotlin学习笔记)