Kotlin 进阶之路8 程序结构

Kotlin 进阶之路 目录

常量

  • val = value,值类型
  • 类似Java的final
  • 不可能重复赋值
- 运行时常量:val x =getX()
- 编译期常量:const val x = 2

变量

  • val = variable
- var x = "HelloWorld"//定义变量
- x = "Hello,China"//再次赋值

类型推导

  • 编译器可以推导量的类型
- val string ="Hello" //推导出String类型
- val int = 5 //Int 类型
- var x = getString() + 5 //String类型 

函数

  • 以特定功能组织起来的代码块
- fun[函数名]([参数列表]):[返回值类型]{[函数体]}
- fun[函数名]([参数列表]) = [表达式]

举例:

- fun sayHi(name:String) { println("Hi,$name") }
- fun sayHi(name:String) = println("Hi,$name")

匿名函数

  • fun([参数列表])...
- val sayHi = fun(name:String) = println("Hi,$name")

编写函数的注意事项

  • 功能单一
  • 函数名要做到顾名思议
  • 参数个数不要太多

Lambda 表达式

  • 匿名函数
  • 写法:{[参数列表]->[函数体,最后一行是返回值]}
- val sum = {a:Int,b:Int->a + b }
Lambda的类型举例
  • ()->Unit
无参,返回值为Unit
  • (Int)->Int
传入整型,返回一个整型
  • (String,(String)->String)->Boolean
- 传入字符串、Lambda表达式,返回Boolean
Lambda表达式的调用
  • 用()进行调用
  • 等价于invoke()
- val sum = {a:Int,b:Int -> a + b}
- sum(2,3)
- sum.invoke(2,3)
Lambda表达式的简化
  • 函数参数调用时最后一个Lambda可以移出去
  • 函数参数只有一个Lambda,调用时小括号可以省略
  • Lambda只有一个参数可默认为it
  • 入参,返回值与形参一致的函数可以用函数引用的方式作为实参传入
fun main(args: Array) {

    println(int2Long(3))
    println(sum(2, 3))
    println(sum2(5, 6))
    println(sum.invoke(1, 3))

    val args: Array = arrayOf(1, 2, 3, 4, 5, 6)
    for (i in args) {
        println(i)
    }
    args.forEach(::println)
    println("--------------------------------")
    args.forEach ForEach@{
        if (it == 2) return@ForEach
        println(it)
    }
    println("The End 1.....")
    args.forEach {
        if (it == 3) return
        println(it)
    }
    println("The End 2.....")
}

val int2Long = fun(x: Int): Long {
    return x.toLong()
}

val sum = { arg1: Int, arg2: Int -> arg1 + arg2 }

val sum2 = { arg1: Int, arg2: Int -> println("$arg1 + $arg2 = ${arg1 + arg2}") }
3
5
5 + 6 = 11
kotlin.Unit
4
1
2
3
4
5
6
1
2
3
4
5
6
--------------------------------
1
3
4
5
6
The End 1.....
1
2

类成员

  • 属性:作者说成员变量,类范围内的变量
  • 方法:或者说成员函数,类范围内的函数

函数和方法的区别

  • 函数强调功能本身,不考虑从属
  • 方法的称呼通常是从类的角度出发
  • 叫法不同而已,不要纠结

定义属性

  • 构造方法参数中val/var修饰的都是属性
  • 类内部也可以定义属性

属性访问控制

  • 属性可以定义getter/setter
- val a:Int = 0 //不能定义set()
- get() = field
- var b:Float = 0f //可以定义getter/setter
- set(value){field = value}

属性初始化

  • 属性的初始化尽量在构造方法中完成
  • 无法在构造方法中初始化,尝试降级为局部变量
  • var用lateinit延迟初始化,val用lazy
  • 可空类型谨慎用null直接初始化
class X
//lateinit 延迟初始化
class A {
    var b = 0
    lateinit var c: String
    lateinit var d: X
    val e: X by lazy {
        println("init X")
        X()
    }
    //可空类型谨慎用null直接初始化
    var cc: String? = null
}

fun main(args: Array) {
    println("start")
    val a = A()
    println("init a")
    println(a.b)
    println(a.e)

    a.d = X()
    println(a.d)

    println(a.cc?.length)
}
start
init a
0
init X
chapter3.X@7106e68e
chapter3.X@7eda2dbb
null

基本运算符

  • 任何类可以定义或者重载父类的基本运算符
  • 通过运算符对应的具体函数来定义
  • 对参数个数作要求,对参数和返回值类型不作要求
  • 不能像Scale一样定义任意运算符

中缀表达式

  • 只有一个参数,且用infix修饰的函数
- class Book{ infix fun on(place:String){...}}
- Book() on "My Desk"

分支表达式

  • if...else
- if(a ==b ) ... else if(a == c) ... else ...
  • 表达式与完备性
- val x = if(b < 0) 0 else b
- val x = if(b < 0) 0 //错误,赋值时,分支必须完备
private const val USERNAME = "kotlin"
private const val PASSWORD = "jetbrains"

private const val ADMIN_USER = "admin"
private const val ADMIN_PASSWORD = "admin"

private const val DEBUG = 1
private const val USER = 0

fun main(args: Array) {

    //1.变量赋值
//    var mode = USER
//    if (args.isNotEmpty() && args[0] == "1") {
//        mode = DEBUG
//    }
//2. 表达式给变量赋值
    val mode = if (args.isNotEmpty() && args[0] == "1") {
        DEBUG
    } else {
        USER
    }

    println("请输入用户名:")
    val username = readLine()
    println("请输入密码:")
    val password = readLine()

    if (mode == DEBUG && username == ADMIN_USER && password == ADMIN_PASSWORD) {

        println("管理员登录成功")
    } else if (username == USERNAME && password == PASSWORD) {
        println("登录成功")
    } else {
        println("登录失败")
    }

When 表达式

  • 加强版switch,支持任意类型
  • 支持纯表达式条件分支(类似if)
  • 表达式与完备性
fun main(args: Array) {
    val x = 5
    when (x) {
        is Int -> println("Hello $x")
        in 1..100 -> println("$x is in 1..100")
        !in 1..100 -> println("$x is not in 1..100")
        args[0].toInt() -> println("$x == args[0]")
    }
}
Hello 5

循环语句

for循环
  • 基本写法
- for(element in elements)...
  • 给任意类实现Iterator方法
fun main(args: Array) {

    val args: Array = arrayOf('a', 'b', 'c', 'd')
    for (arg in args) {
        println(arg)
    }
    println("-------------------------------")
    for ((index, value) in args.withIndex()) {
        println("$index -> $value")
    }
    println("-------------------------------")
    for (indexedValue in args.withIndex()) {
        println("${indexedValue.index} -> ${indexedValue.value}")
    }
    println("-------------------------------")
    val list = MyIntList()
    list.add(1)
    list.add(2)
    list.add(3)

    for (i in list) {
        println(i)
    }
}

class MyIterator(val iterator: Iterator) {
    operator fun next(): Int {
        return iterator.next()
    }

    operator fun hasNext(): Boolean {
        return iterator.hasNext()
    }
}

class MyIntList {
    private val list = ArrayList()

    fun add(int: Int) {
        list.add(int)
    }

    fun remove(int: Int) {
        list.remove(int)
    }

    operator fun iterator(): MyIterator {
        return MyIterator(list.iterator())
    }
}
a
b
c
d
-------------------------------
0 -> a
1 -> b
2 -> c
3 -> d
-------------------------------
0 -> a
1 -> b
2 -> c
3 -> d
-------------------------------
1
2
3
While循环

类似于C语言

跳过和终止循环
  • 跳过当前循环用continue
  • 终止循环用break
  • 多层循环嵌套的终止结合便签使用
- Outter@for(...){
     Inner@while(i < 0){ if(...) break } //结束while循环
      Inner@while(i < 0){ if(...) break@Outter }//结束外层for循环
}

具名参数

  • 给函数的时参附上形参
  • 举例:
- fun sum(arg1:Int,arg2:Int) = arg1 + arg2
- sum(arg1 = 2, arg2 = 3)

变长参数

  • 某个参数可以接收多个值
  • 可以不为最后一个参数
  • 如果传参时有歧义,需要使用具名参数
fun main(vararg args: String) {
//    for (arg in args) {
//        println(arg)
//    }
    hello(18.0,1,2,3,4,string ="Hello")

    val array = intArrayOf(5,4,3,2,1)
    hello(18.0,*array,string ="Hello")
}

fun hello(double: Double,vararg ints: Int, string: String) {
    ints.forEach(::println)
}
1
2
3
4
5
4
3
2
1

本章知识点示例

fun main(args: Array) {
    while (true) {
        try {

            println("请输入算式例如:3 + 4")
            val input = readLine() ?: break
            if (input != null) {
                val splits = input.trim().split(" ")
                if (splits.size < 3) {
                    throw IllegalArgumentException("参数个数不对")
                }
                val arg1 = splits[0].toDouble()
                val op = splits[1]
                val arg2 = splits[2].toDouble()
                println("$arg1 $op $arg2 = ${Operator(op).apply(arg1, arg2)}")


            }
        } catch (e: NumberFormatException) {
            println("您输入的数字格式不对")
        } catch (e: IllegalArgumentException) {
            println("请输入用空格分隔的三个参数")
        } catch (e:Exception){
            println("未知异常:${e.message}")
        }
        println("再来一发?[Y]")
        val cmd = readLine()
        if (cmd == null || cmd.toLowerCase() != "y") {
            break
        }
    }

}

class Operator(op: String) {
    val opFun: (left: Double, right: Double) -> Double

    init {
        opFun = when (op) {
            "+" -> { l, r -> l + r }
            "-" -> { l, r -> l - r }
            "*" -> { l, r -> l * r }
            "/" -> { l, r -> l / r }
            "%" -> { l, r -> l % r }
            else -> {
                throw UnsupportedOperationException(op)
            }
        }

    }

    fun apply(left: Double, right: Double): Double {
        return opFun(left, right)
    }
}
请输入算式例如:3 + 4
566.33.33 + 1
您输入的数字格式不对
再来一发?[Y]
y
请输入算式例如:3 + 4
23+1
请输入用空格分隔的三个参数
再来一发?[Y]
y
请输入算式例如:3 + 4
5 + 6 
5.0 + 6.0 = 11.0
再来一发?[Y]

你可能感兴趣的:(Kotlin 进阶之路8 程序结构)