kotlin 读书笔记

1 匿名函数

  • 函数的定义 就是 把表达式或语句 放到一对 花括号里
     {
      	表达式 或 语句
      }
    
  • 函数类型
    kotlin 中 参数 或 返回值 都是类型。 函数作为 ‘一等公民’ 也是一种类型。 使用 (参数)-> 返回类型 表示。
   fun greetingFunction() : Strng     //返回一个,
   fun greetingFunction() : () ->Unit  // 返回 一个 函数, 该函数 没有参数, 返回值 为 Unit
   fun greetingFunction() : (Int) ->String// 返回 一个 函数, 该函数接收1个Int参数, 返回值String 的 函数。
	
  • Lambda 表达式
    在Kotlin中, 我们把 匿名函数的定义 称为 Lambda表达式 。
    lambda 函数体里 不能有 return 关键字
    Lamdda表达式 默认以函数体 最后一行 代码的值,作为 返回值。

  • it 关键字
    当 lambda 表达式 只定义了 一个参数时,可以用 it 来表示参数名。

fun IntRange.pickNum(function: (Int) -> Boolean): List<Int> {
    val resultList = mutableListOf<Int>()
    for (i in this) {
        if (function(i)) resultList.add(i)
    }
    return resultList
}
println(list.pickNum{ it % 10 == 0 })
  • 调用lambda 时 简略写法

如果函数只有一个参数,且参数为函数类型,调用时可以省略小括号

fun IntRange.pickNum(function: (Int) -> Boolean): List<Int> {
    val resultList = mutableListOf<Int>()
    for (i in this) {
        if (function(i)) resultList.add(i)
    }
    return resultList
}
 println(list.pickNum({ x: Int -> x % 10 == 0 }))
 println(list.pickNum { x: Int -> x % 10 == 0 })

如果有多个参数,并且最后一个参数是函数类型,调用时可以将函数参数移到括号外

fun IntRange.pickNum(need :Int ,find : Int , function: (Int) -> Boolean): List<Int> {
    val resultList = mutableListOf<Int>()
    for (i in this) {
        if (function(i)) resultList.add(i)
    }
    return resultList
}

 println(list.pickNum(10,100,{ x: Int -> x % 10 == 0 }))
 println(list.pickNum(10,100) { x: Int -> x % 10 == 0 })
  • lambda 是闭包的
    在kotlin中,匿名函数能 修改 和引用,定义在自己作用域之外的变量。
fun configureFun(): (String) -> String {
    val value = "hospitals"
    var number = 8
    return { name: String ->
        val year = 2019
        number++
        println("this is result $value number = $number")
        "welcome to here ,$name ! (copyright $year)"
    }
}

fun main() {
    val greetingFun = configureFun()
    println(greetingFun("老王"))
    println(greetingFun("老李"))
    println(greetingFun("老张"))
}

打印结果

this is result hospitals number = 9
welcome to here ,老王 ! (copyright 2019)
this is result hospitals number = 10
welcome to here ,老李 ! (copyright 2019)
this is result hospitals number = 11
welcome to here ,老张 ! (copyright 2019)

从结果中,可以发现。外部的变量 value number ,可以在lambda函数里直接调用 和修改。

2 null安全的操作符

  • 定义 一个 返回值可以为空的方法
fun readLine() :String ?
  • String 是 String? 的子类

  • 安全调用操作符 ?. 使用let 的 安全调用

	fun readLine(): String? {
        val number = listOf(1, 2, 3).shuffled().first()
        if (number > 2) {
            return "$number"
        }
        return null
    }
  
    val beverage = readLine()?.let { 
        if(it =="4"){
            "${it.toInt() +3 }"
        }else{
            "3"
        }
    }
  • 非空断言操作符 !!.

  • 空合并操作符 ?:
    当 readLine() 返回null时,beverage2 = “123”

 val  beverage2 = readLine() ?: "123"

3 标准库函数

  • apply
    源码:
public inline fun <T> T.apply(block: T.() -> Unit): T {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    block()
    return this
}

参数是 this ,一般使用与 配置某个对象, 返回为 调用的对象本身。

val  menuFile = File("xxxx").apply { 
        setReadable(false)
        setWritable(true)
        setExecutable(false)
    }
  • let
    源码:
public inline fun <T, R> T.let(block: (T) -> R): R {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    return block(this)
}

参数时 it ,返回 lambda表达的值,做空值处理。

fun formatGreeting(vipGuest: String?): String {
        return vipGuest?.let { "welcome $it. go straight back" } 
            ?: "welcome to the tavern. you will be seated shortly"
}
  • run
    源码:
 public inline fun <T, R> T.run(block: T.() -> R): R {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    return block()
}

和 apply 类似, 参数为this ,但 返回 lambda表达的值
run 常用语 函数的链式调用,能让代码逻辑更清晰

    fun nameIsLong(name:String) = name.length >=20
    fun playerCreatMessage( nameTooLong:Boolean) :String{
        return if(nameTooLong){
            "Name is too long,Please choose another name"
        }else{
            "Welcome to Adventurer"
        }
    }
    //原代码
    println(playerCreatMessage(nameIsLong("Polarise,Supreme Master of Netmask")))
    
    //run 优化后
    "Polarise,Supreme Master of Netmask"
        .run(::nameIsLong)
        .run(::playerCreatMessage)
        .run(::println)
  • with
    with 是 run 的变体,功能一样。 不推荐使用, 一般用run替代。

  • also
    源码:

public inline fun <T> T.also(block: (T) -> Unit): T {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    block(this)
    return this
}

和let 类似,参数 it , 返回对象本身。

val numbers = mutableListOf("one", "two", "three")
numbers
    .also { println("The list elements before adding new one: $it") }
    .add("four")
  • takeIf
    源码:
public inline fun <T> T.takeIf(predicate: (T) -> Boolean): T? {
    contract {
        callsInPlace(predicate, InvocationKind.EXACTLY_ONCE)
    }
    return if (predicate(this)) this else null
}

功能类型 if else 。 参数 it , 返回 true 或者 null

val str = "Hello"
val caps = str.takeIf { it.isNotEmpty() }?.toUpperCase()

fun displaySubstringPosition(input: String, sub: String) {
    input.indexOf(sub).takeIf { it >= 0 }?.let {
        println("The substring $sub is found in $input.")
        println("Its start position is $it.")
    }
}

4 构造函数

  • 主构造函数
class Cat( master: String, var name:String, val age :Int, color: Color = Color.BLACK){
    
}

需要注意的是主构造函数不包含任何代码,初始化程序块用于初始化代码

  • 次级构造函数
class Cat( master: String, var name:String, val age :Int, color: Color = Color.BLACK){

    constructor(master: String): this(master,age = 3, name ="喵喵")
        
}

我们可以在同一类中使用主构造函数和次级构造函数。通过在一个类中使用主和次级构造函数,次级构造函数需要授权给主构造函数,也就是次级构造函数会直接或者间接调用主构造函数。使用this()关键字对同一个类中的另一个构造函数进行授权。
构造函数 参数 可以是 var val ,也可以给初始值。

  • 初始化顺序
    1 主构造函数里声明的属性
    2 类级别的属性赋值
    3 init 初始代码块的属性赋值 和 函数调用
    4 次级构造函数里的 属性赋值 和 函数调用
    特殊说明: 2 3 条,init 初始化代码块 和 类级别的属性赋值, 顺序 取决于 定义的先后顺序。

5 Object 关键字

object 的使用 有3种方式: 对象声明 对象表达式 伴生对象

  • 对象声明
    单例模式
object Game{
    const val  TAG = "lsh"
    init {
        println("这是 一个 单例")
    }
    
    fun getSomething() : String {
        return "给你点 惊喜!"
    }
}

fun main(args: Array<String>) {
    Game.getSomething()
    var tag = Game.TAG
}
  • 对象表达式
    创建继承某个(或某些)类型的匿名类的对象,这些类型可以是接口 抽象类 普通类
button.setOnClickListener(object: View.OnClickListener {
          override fun onClick(v: View?) {
              Log.d(MainActivity::class.java.simpleName, "click button")
          }
      })
      
open class Man(_name: String) {
    val name = _name
}

interface Flyable {
    fun fly()
}

interface SuperHearing {
    fun hearSubtleNoises()
}

fun main(args: Array<String>) {
    val superMan = object : Man("Clark"),Flyable,SuperHearing{
        override fun fly() {
            println("i can  fly")
        }

        override fun hearSubtleNoises() {
            println(" hearSubtleNoises ")
        }
    }
}

对象表达式后面可以不跟任何类或者接口,这时它仅仅表示一个对象,封装一些数据和方法

  val litCat  = object {
        val name = "喵喵"
        fun eat(){
            println("我 吃 鱼")
        }
    }
    
    litCat.eat()
    litCat.name
  • 伴生对象
    关键字 companion object , 可以理解 为 java 里的 静态变量 静态方法。
class MyActivity : AppCompatActivity() {

    companion object {
        const val TAG = "MyActivity"
        @JvmStatic // 如果在 Java 代码中调用此方法,必须加上这个注解,才能编译出静态方法
        fun start(context: Context) {
            val starter = Intent(context, MyActivity::class.java)
            context.startActivity(starter)
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值